Есть ли способ присоединиться к BTreeSet на пустом месте, потребляя его для получения строки, не помещая каждый элемент в строку? - PullRequest
0 голосов
/ 18 января 2019

Есть ли способ присоединиться к BTreeSet на пустом месте, потребляя его для получения строки, в которой каждый элемент отделен пробелом, кроме как итерацией по каждому элементу и нажатием на строку?

Мой набор может быть очень большим, максимум 10 ГБ, поэтому я хотел бы ограничить использование памяти.

type `std::collections::BTreeSet<std::vec::Vec<u8>>`

Я использую био-ящик для создания обратных комплиментов строк ДНК, которые принимает и возвращает Vec<u8> (или, по крайней мере, возвращает Vec<u8>), чтобы избежать чтобы конвертировать туда и обратно на некоторых шагах, я хочу сохранить их как таковые.

Вот пример:

let dna_pieces = std::fs::read_to_string(path_dna_file).expect("Unable to read file");
let dna_pieces = dna_pieces.split(" ");

let mut dna_pieces_set = BTreeSet::new();

// first adds a small set to the tree
for dna_piece in dna_pieces {
    let dna_bytes = species_kmer.to_owned().into_bytes();
    dna_pieces_set.insert(dna_bytes);
}

// then adds a bigger other set to the same tree
let dna_pieces_big_list = std::fs::read_to_string(path_dna_file_big).expect("Unable to read file");
let dna_pieces_big_list = dna_pieces_big_list.split(" ");
for dna_piece in dna_pieces_big_list {
    let dna_bytes = dna_piece.to_owned().into_bytes();
    let dna_bytes_to_rev = dna_piece.to_owned().into_bytes();
    let reverse_complement = bio::alphabets::dna::revcomp(dna_bytes_to_rev);
    if !dna_pieces_set.contains(&reverse_complement) {
        dna_pieces_set.insert(dna_bytes);
    }
}

// format the treeset into a string output_unique_dna_pieces...

std::fs::write(path_unique_dna_pieces, output_unique_dna_pieces).expect("Unable to write file");

1 Ответ

0 голосов
/ 18 января 2019

Это невозможно. Если вы хотите избежать выделения всего содержимого набора дважды, у вас действительно есть два варианта:

  1. Переключитесь на HashSet, чтобы вы могли использовать метод drain. К сожалению, этот метод еще не существует для BTreeSet.

    let mut output = Vec::new(); // use with_capacity if you know an upper bound on the size
    for x in hash_set.drain() {
        output.extend_from_slice(&x);
        output.push(b' '); // add the space
    }
    
  2. Запись непосредственно в файл вместо создания временной структуры данных. Используйте BufWriter для меньшего количества вызовов ввода-вывода.

    let buffer = File::create("filename.txt")?;
    let mut writer = BufWriter::new(buffer);
    for dna_piece in dna_pieces_set.iter() {
        writer.write(dna_piece)?;
        writer.write(b" ")?; // add the space
    }     
    
...