同功能下TypeScript实现为何比Rust实现效率更高?
账单文本解析:Rust与TypeScript实现对比(Tauri项目)
需求说明
实现函数读取预加载的账单.txt文件内容,将每行交易解析为指定数据结构后返回。交易行格式示例:2023/1/7 15:14 - goods1x2 goods2x2 : 24.19 dollars,需映射到Item和Transaction结构。
在Tauri项目中完成双语言实现后,性能测试结果如下:
- 处理100万行数据:TypeScript耗时约2秒,Rust耗时约9秒
- 仅处理1行数据:TypeScript仍比Rust更快
Rust实现
数据结构
struct Item { content: String, count: String, price: String, } struct Transaction { date: String, time: String, status: i32, total_amount: String, account: String, items: Vec<Item>, }
解析函数
pub fn text_bill_analysis(text: String) -> tauri::ipc::Response { let start = std::time::Instant::now(); let mut transactions: Vec<Transaction> = Vec::new(); let re = Regex::new(r"(paypay|bank2|income)").unwrap(); for line in text.lines() { let line = match line.find("--") { Some(x) => line.split_at(x).0, None => line, }; let line = line.trim(); if line.is_empty() { continue; } let parts: Vec<&str> = line.split_whitespace().collect(); if parts.len() < 2 { continue; } let date_parts: Vec<&str> = parts[0].split('/').collect(); if date_parts.len() != 3 { continue; } let year = date_parts[0]; let month = format!("{:02}", date_parts[1].parse::<i32>().unwrap_or(0)); let day = format!("{:02}", date_parts[2].parse::<i32>().unwrap_or(0)); let date = format!("{}/{}/{}", year, month, day); let time_parts: Vec<&str> = parts[1].split(':').collect(); if time_parts.len() != 2 { continue; } let hour = format!("{:02}", time_parts[0].parse::<i32>().unwrap_or(0)); let minute = format!("{:02}", time_parts[1].parse::<i32>().unwrap_or(0)); let time = format!("{}:{}", hour, minute); let status = if line.contains("income") { 1 } else if line.contains("balance") { 2 } else { 0 }; let unit = parts.last().unwrap_or(&""); if *unit != "dollars" { continue; } let total_amount = match parts.iter().nth_back(1) { Some(x) => format!("{:.2}", x.parse::<f64>().unwrap_or(0.0)), None => continue, }; let account = if line.contains("paypay") { "paypay" } else if line.contains("bank2") { "bank2" } else { "bank1" }; let mut items: Vec<Item> = Vec::new(); let parts_split: Vec<&str> = line.split(" - ").collect(); if parts_split.len() < 2 { continue; } let parts_colon: Vec<&str> = parts_split[1].split(" : ").collect(); if parts_colon.len() < 2 { continue; } let parts_filtered: Vec<&str> = parts_colon[0] .split_whitespace() .filter(|&x| !re.is_match(x)) .collect(); if parts_filtered.is_empty() { items.push(Item { content: "income".to_string(), count: "1".to_string(), price: "null".to_string(), }); } let n = parts_filtered.len() as i32; for part in parts_filtered { let cleaned_part = re.replace_all(part, "").trim().to_string(); if cleaned_part.is_empty() { continue; } let item_parts: Vec<&str> = cleaned_part.split('x').collect(); let content = item_parts[0].to_string(); let count = item_parts .get(1) .map_or(1, |x| x.parse::<i32>().unwrap_or(1)) .to_string(); items.push(Item { content, count, price: if n == 1 { total_amount.clone() } else { "null".to_string() }, }); } transactions.push(Transaction { date, time, status, total_amount, account: account.to_string(), items, }); } let elapsed = start.elapsed(); println!("rust: {:?}", elapsed); println!("len: {:?}", transactions.len()); tauri::ipc::Response::new(serde_json::to_string(&transactions).unwrap()) }
TypeScript实现
数据结构
interface Item { content: string count: string price: string } interface Transaction { date: string time: string status: number totalAmount: string account: string items: Item[] }
解析函数
function textBillAnalysisTs(text: string): Transaction[] { console.time('ts') const transactions: Transaction[] = [] const lines = text.split('\n') for (const _line of lines) { const lineWithoutComment = _line.split('--')[0] const line = lineWithoutComment.trim() if (line === '') continue const parts = line.split(/\s+/) if (parts.length < 3) continue const dateParts = parts[0].split('/') if (!dateParts || dateParts.length !== 3) continue const year = dateParts[0] const month = dateParts[1].padStart(2, '0') const day = dateParts[2].padStart(2, '0') const date = `${year}/${month}/${day}` const timeParts = parts[1].split(':') if (!timeParts || timeParts.length !== 2) continue const hour = timeParts[0].padStart(2, '0') const minute = timeParts[1].padStart(2, '0') const time = `${hour}:${minute}` const status = line.includes('income') ? 1 : line.includes('balance') ? 2 : 0 const unit = parts[parts.length - 1] if (unit !== 'dollars') continue const totalAmount = parseFloat(parts[parts.length - 2]).toFixed(2) const account = line.includes('paypay') ? 'paypay' : line.includes('bank2') ? 'bank2' : 'bank1' const items: Item[] = [] const partsSplit = line.split(' - ') const partsColon = partsSplit[1]?.split(' : ') if (!partsColon) continue const partsFiltered = partsColon[0] .split(/\s+/) .filter((x) => !['paypay', 'bank2', 'income'].includes(x)) .map((x) => x.trim()) if (partsFiltered.length === 0) { items.push({ content: 'income', count: '1', price: 'null' }) } const n = partsFiltered.length for (const part of partsFiltered) { const cleanedPart = part .replace(/(paypay|bank2|income)/g, '') .trim() if (cleanedPart === '') continue const itemParts = cleanedPart.split('x') const content = itemParts[0] || '' const count = Math.max(parseInt(itemParts[1] || '1', 10), 1).toString() items.push({ content, count, price: n === 1 ? totalAmount : 'null' }) } transactions.push({ date, time, status, totalAmount, account, items }) } console.timeEnd('ts') return transactions }
支持的输入示例
2023/01/7 05:04 - goods1x2 goods2 : 4240.20 dollars 2023/01/07 5:4 - goods1x2 goods2 : 4240 dollars 2023/01/07 5:4 - goods1x2 goods2 : 4240.2 dollars 2023/01/07 5:4 - goods1x2 goods2 : 4240.20 dollars 2023/01/07 5:04 - goods1x2 goods2 : 4240 dollars 2023/01/07 5:04 - goods1x2 goods2 : 4240.2 dollars 2023/01/07 5:04 - goods1x2 goods2 : 4240.20 dollars 2023/01/07 05:4 - goods1x2 goods2 : 4240 dollars 2023/01/07 05:4 - goods1x2 goods2 : 4240.2 dollars 2023/01/07 05:4 - goods1x2 goods2 : 4240.20 dollars 2023/01/07 05:04 - goods1x2 goods2 : 4240 dollars 2023/01/07 05:04 - goods1x2 goods2 : 4240.2 dollars 2023/01/07 05:04 - goods1x2 goods2 : 4240.20 dollars
内容的提问来源于stack exchange,提问作者XunJi kora
相关产品推荐
相关产品推荐

