具体的には、私は.lines().filter_map()
で特定の行を除外して標準を取ります。その結果をcsv::Reader
としたいと思います。イテレータ用のstd :: io :: Readを実装するには<Item=String>?
答えて
最も簡単な解決策は巨大なバッファに一度にすべての入力を読み、そこから読み取るために、次のようになります。
let iterable = ["h", "e", "l", "l", "o"];
let combined_string: String = iterable.iter().cloned().collect();
let bytes = combined_string.into_bytes();
let mut buf = vec![];
let bytes = (&bytes[..]).read_to_end(&mut buf).unwrap();
assert_eq!(&buf[..bytes], b"hello");
あなたが本当にメモリにすべてのロードを避けるために必要であれば、それが実現することが可能ですラッパーを使用することができますが、使用可能なバイト数と読み取るバイト数が常に一致するとは限らないため、いくつかの厄介なビットがあります。あなたは自分の位置を追跡し、時にはそれ以上のデータから読み続けてもらうために、いくつかの一時的な値に保持する必要があります。
use std::io::{self, Read};
use std::cmp;
/// Eagerly consumes elements from the underlying iterator instead of
/// returning partial reads.
struct IteratorAsRead<I>
where
I: Iterator,
{
iter: I,
value: Option<I::Item>,
offset: usize,
}
impl<I> IteratorAsRead<I>
where
I: Iterator,
{
pub fn new<T>(iter: T) -> Self
where
T: IntoIterator<IntoIter = I, Item = I::Item>,
{
IteratorAsRead {
iter: iter.into_iter(),
value: None,
offset: 0,
}
}
}
impl<I> Read for IteratorAsRead<I>
where
I: Iterator,
I::Item: AsRef<[u8]>,
{
fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> {
let mut copied = 0;
loop {
match self.value.take() {
None => {
match self.iter.next() {
None => {
return Ok(copied);
}
Some(value) => {
self.value = Some(value);
}
}
}
Some(original_value) => {
let entire_value_len = {
let entire_value = original_value.as_ref();
// Skip over bytes we already copied
let value = &entire_value[self.offset..];
let buf = &mut buf[copied..];
// Make the slices the same length
let len_to_copy = cmp::min(value.len(), buf.len());
let value = &value[..len_to_copy];
let buf = &mut buf[..len_to_copy];
// Copy
buf.copy_from_slice(value);
// Advance our values
copied += len_to_copy;
self.offset += len_to_copy;
entire_value.len()
};
// If we completely used the value, reset our counters,
// otherwise put it back for the next call.
if self.offset == entire_value_len {
self.offset = 0;
} else {
self.value = Some(original_value);
}
}
}
// If we've filled the buffer, return it
if copied == buf.len() {
return Ok(copied);
}
}
}
}
#[test]
fn small_pieces_are_combined() {
let iterable = ["h", "e", "l", "l", "o"];
let mut reader = IteratorAsRead::new(&iterable);
let mut buf = vec![];
let bytes = reader.read_to_end(&mut buf).unwrap();
assert_eq!(&buf[..bytes], b"hello");
}
#[test]
fn partial_reads() {
let iterable = ["hello"];
let mut reader = IteratorAsRead::new(&iterable);
let mut buf = [0; 2];
let bytes = reader.read(&mut buf).unwrap();
assert_eq!(&buf[..bytes], b"he");
let bytes = reader.read(&mut buf).unwrap();
assert_eq!(&buf[..bytes], b"ll");
let bytes = reader.read(&mut buf).unwrap();
assert_eq!(&buf[..bytes], b"o");
}
あなたはそれを読み込む部分戻ることができた場合Read::read
の簡単な実装があります。 Shepmasterと同様の構造から始めましょう。
use std::io::{self, Read};
struct IteratorAsRead<I>
where
I: Iterator,
{
iter: I,
leftover: Option<(I::Item, usize)>,
}
impl<I> IteratorAsRead<I>
where
I: Iterator,
{
pub fn new<T>(iter: T) -> Self
where
T: IntoIterator<IntoIter = I, Item = I::Item>,
{
IteratorAsRead {
iter: iter.into_iter(),
leftover: None,
}
}
}
すると最初から読むために空でない文字列を見つけるバッファにそれを書き込もうとすると、必要であれば最終的には任意の残り物を格納することで機能を実装します。
impl<I> Read for IteratorAsRead<I>
where
I: Iterator,
I::Item: AsRef<[u8]>,
{
fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> {
let (leftover, skip) = match self.leftover.take() {
Some(last) => last,
None => match self.iter.find(|next| !next.as_ref().is_empty()) {
Some(next) => (next, 0),
None => return Ok(0),
}
};
let read = (&leftover.as_ref()[skip..]).read(buf)?;
if skip + read < leftover.as_ref().len() {
self.leftover = Some((leftover, skip + read));
} else {
self.leftover = None;
}
return Ok(read);
}
}
私は 'std :: io :: Cursor'を使ってもっと簡単なバージョンを投稿しました。私の答えを見てください。 –
標準ライブラリは、バッファ内の位置と共にバッファをラップタイプstd::io::Cursor
を提供します。これはさらにVeedrac's answerで与えられるコードを簡略化するために使用することができる。
use std::io::{self, Cursor, Read};
struct IteratorAsRead<I>
where
I: Iterator,
{
iter: I,
cursor: Option<Cursor<I::Item>>,
}
impl<I> IteratorAsRead<I>
where
I: Iterator,
{
pub fn new<T>(iter: T) -> Self
where
T: IntoIterator<IntoIter = I, Item = I::Item>,
{
let mut iter = iter.into_iter();
let cursor = iter.next().map(Cursor::new);
IteratorAsRead { iter, cursor }
}
}
impl<I> Read for IteratorAsRead<I>
where
I: Iterator,
Cursor<I::Item>: Read,
{
fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> {
while self.cursor.is_some() {
let read = self.cursor.as_mut().unwrap().read(buf)?;
if read > 0 {
return Ok(read);
}
self.cursor = self.iter.next().map(Cursor::new);
}
Ok(0)
}
}
非語彙的寿命を使用して、read()
メソッド内のコードはわずかに(play link)を簡略化することができます。
- 1. のstd ::リスト<std::string> ::イテレータはstd ::文字列にする
- 2. 'Seek'が実装されていない場合、 'std :: io :: Read'特性からデータを進めるには?
- 3. Vecまたはスライスから(std :: io :: Read)を読むには?
- 4. のstd ::ベクトル< T > ::イテレータ
- 5. 私のstd :: list実装のイテレータは動作しません
- 6. ヒューズC++ドライバ - read()の実装
- 7. std :: listの実装<bool>
- 8. なぜstd :: io :: Readの関数がバッファを取るのですか?
- 9. どのようにstdのようなイテレータのカスタム実装を実現するには?
- 10. 高速イテレータ実装
- 11. std :: sortはイテレータのみを使用してスワップ操作をどのように実装しますか?
- 12. pydのイテレータを実装する
- 13. std :: iteratorを実装する
- 14. Map <String、String>クラスとイテレータの使用を実装しているJava
- 15. std :: io :: readにキャスト&[u8]が原因の問題が発生しました。
- 16. カスタムIntoIterator :: Itemのstd :: fmt :: Displayを実装するにはどうしたらいいですか?
- 17. Java - 戦略でイテレータを実装する
- 18. Read buffer(VC++)からFTPClient用のネットワークストリームを実装する
- 19. イテレータを使用してstd :: listに挿入するには?
- 20. 演算子を実装する方法>>(std :: istream&、std :: array <char, N>&)?
- 21. イテレータからすべての関数を実装してイテレータを実装しないのはなぜですか?
- 22. std :: set - 演算子を実装する正しい方法<?
- 23. C++ 11 `std :: string ToString(std :: tuple <Args...>&t)`の実装方法は?
- 24. Iterator <Item = io :: Result <u8>>をパニックにすることなくio :: Result <Vec<u8>に変換できますか?
- 25. std :: list :: clearはstd :: list :: endイテレータを無効にしますか?
- 26. std :: is_nothrow_copy_constructibleの実装は何ですか?
- 27. no-op std :: ostreamの実装
- 28. libC++ std :: condition_variable_anyの実装
- 29. std :: forward実装の違い
- 30. std :: promiseのVC++実装
この質問は、irc.mozilla.orgの#rustのRust IRCユーザー "njoodle"に由来していますが、その間にIRCログが機能していないように見えるので、より完全なauthorshipリンクを提供することはできません。 – Shepmaster