Я погружаю свои пальцы в Rust и не могу понять, как сравнивать строки двух CSV-файлов. Я подозреваю, что моя трудность возникает из-за попыток решить проблему совершенно неверным образом, и поэтому я использую все преимущества stackoverflow.
Я пишу простую программу, которая читает два файла csv известных полей, а затем сравнивает расстояние редактирования каждого элемента столбца j в csv1 с каждым элементом столбца j в csv2 для всех столбцов j в J. На данный момент Мой код только сравнивает первую строку csv1 со всеми строками csv2.
Мой шаблон:
- считайте csvs в
struct Reader
, используя csv и serde (все хорошо).
- Создайте
struct Compare
, который содержит две строки типа Reader, по одной от каждого CSV.
- Напишите метод для Compare, который возвращает строковые расстояния.
У меня есть основные фрагменты кода ниже, и все это можно найти на ржавой площадке здесь .
struct Record
будет содержать строку,
#[derive(Debug,Deserialize)]
struct Record {
mp: String,
party: String,
constit: String,
position: String,
group: String,
}
и struct Compare
содержит два ряда вместе. У меня есть это заимствовать значение, потому что я продолжал получать ошибку копирования - но возможно это - то, где мои проблемы начинаются!
#[derive(Debug)]
struct Compare<'a> {
dfa: &'a Record,
dfb: &'a Record,
}
Здесь я реализую метод для сравнения, который вычисляет расстояние Джаро-Винклера для каждого элемента двух строк и возвращает другой тип структуры, определенный в другом месте (полный файл см. Выше в ссылке на ржавую площадку выше):
impl <'a> Compare<'a> {
fn jwdist(&self) -> Stringcomps {
let res = Stringcomps {
mp: strsim::jaro_winkler(&self.dfa.mp, &self.dfb.mp),
party: strsim::jaro_winkler(&self.dfa.party, &self.dfb.party),
constit: strsim::jaro_winkler(&self.dfa.constit, &self.dfb.constit),
position: strsim::jaro_winkler(&self.dfa.position, &self.dfb.position),
group: strsim::jaro_winkler(&self.dfa.group, &self.dfb.group),
};
res
}
}
Следующий бит кода запускает функцию (с некоторыми игрушечными данными). Он выдает неправильный вывод, поскольку сравнивает только первую строку первого файла CSV со всеми строками другого файла CSV:
fn run() -> Result<(), Box<Error>> {
// get first df
let data1 = "mp,party,constit,position,group\n
george,con,bath,whip,no\n
bob,lab,oxford,backbench,yes";
let data2 = "mp,party,constit,position,group\n
goerge,can,both,wihp,no\n
bob,lob,ofxord,backbenth,yes";
let mut rdr = csv::Reader::from_reader(data1.as_bytes());
// get second df
let mut rdr2 = csv::Reader::from_reader(data2.as_bytes());
// iterate through both and compare
for result in rdr.deserialize() {
let record: Record = result?;
for result2 in rdr2.deserialize() {
let record2: Record = result2?;
let comp = Compare{
dfa: &record,
dfb: &record2,
};
println!("{:?} compared to {:?}: {:?}", comp.dfa.mp,
comp.dfb.mp, comp.jwdist());
}
}
Ok(())
}
fn main() {
if let Err(err) = run() {
println!("error running example: {}", err);
process::exit(1);
}
}
Я пытался исправить свои проблемы, инициализируя объект comp
перед вторым циклом for, но я не могу заставить его работать. Для инициализации требуется метод по умолчанию, который я пытался написать для записи. Я думаю, что у меня все заработало, но потом возникли проблемы, потому что время жизни объекта, который я назначил во втором цикле for, было слишком коротким и не сохранялось достаточно долго, чтобы его можно было напечатать. Это убедило меня в том, что я, возможно, решаю проблему неправильно.
Заранее извиняюсь: это педагогический проект, поэтому я здесь, чтобы получить образование.