gpt4 book ai didi

JavaScript - 将空格分隔的文本文件读入数组并用作查找表

转载 作者:行者123 更新时间:2023-11-30 06:15:08 25 4
gpt4 key购买 nike

首先:我是 JavaScript 的绝对初学者,两周前开始每天学习很多小时。我在 GNU/Linux 上运行一个 node.JS 服务器,我尝试了很多变体来实现这个目标。不幸的是我卡住了,不知道如何继续。

我有一个包含空格和换行符的文本文件,该文件包含大约 > 2000 行的内容。我想将此文本文件读入我的 javascript 程序,以便稍后用作查找表。我不确定我是否需要对它进行 JSON 字符串化以供以后使用,也许将它保留为一个对象/数组很简单,我可以稍后将其用于我的查找函数。我只想从这个文本文件中提取那些包含字符“#”的行,并将其用作分隔符。所有其他行都可以忽略。每行代表一个数据集、元素、对象或任何正确调用的内容。最终目标是:用户请求“Apple”,他应该得到“-9.99”和“BTW”(例如)作为答案。这是原始文本文件的示例:

 Sugar#    1051#      331#     BAD#     1.23#    -4.56#    -5.0#  WWF#
N3T;
Apple# 551# 3815# F3W# 5.55# -9.99# -1.0# BTW#
BBC;
Berry# 19# 22# FF# 19.5# -12.34# 5.0# CYA#
T1K;

它应该代表 3 个元素,每个元素包含 8 对:

 name: 'Sugar'
sec: 1051
ter: 331
wrd: 'BAD'
a: 1.23
b: -4.56
c: -5.0
spon: 'WWF'

name: 'Apple'
sec: 551
ter: 3815
wrd: 'F3W'
a: 5.55
b: -9.99
c: -1.0
spon: 'BTW'

name: 'Berry'
sec: 19
ter: 22
wrd: 'FF'
a: 19.5
b: -12.34
c: 5.0
spon: 'CYA'

一开始我尝试使用fs.readFileSync 将整个文本文件作为字符串读取但没有成功。失望的是,我尝试了另一种方法 readline 来读取我的文本文件 line-by-line 并进行过滤,因为我在网上获得的印象是这种方法更容易内存-友好,甚至可以读取非常大的文件。虽然我很确定 3000 行是一个笑话数字:)

这是我使用 readline 时的代码:

const fs = require('fs');
const readline = require('readline');

function readAndFilter (source, data) {
var fields;
var obj = new Object;
var arr = new Array;

const readAndFilter = readline.createInterface({
input: fs.createReadStream('test.in'),
crlfDelay: Infinity
});

readAndFilter.on('line', (line) => {
if ( line.match( /#/ ) ) {
fields = line.split( '#' ).slice();
obj.name = fields[0].trim();
obj.sec = fields[1].trim();
obj.ter = fields[2].trim();
obj.wrd = fields[3].trim();
obj.a = fields[4].trim();
obj.b = fields[5].trim();
obj.c = fields[6].trim();
obj.spon = fields[7].trim();

console.log(obj);
// let jsonView = JSON.stringify(obj);
// arr.push(obj);
}
});

readAndFilter.on('close', function() {
return arr;
});

}

readAndFilter();

这是代码输出的内容(请注意,我通过为每行输出添加时间戳来自定义我的控制台日志):

 2019-06-16 14:40:10 { name: 'Sugar',
sec: '1051',
ter: '331',
wrd: 'BAD',
a: '1.23',
b: '-4.56',
c: '-5.0',
spon: 'WWF' }
2019-06-16 14:40:10 { name: 'Apple',
sec: '551',
ter: '3815',
wrd: 'F3W',
a: '5.55',
b: '-9.99',
c: '-1.0',
spon: 'BTW' }
2019-06-16 14:40:10 { name: 'Berry',
sec: '19',
ter: '22',
wrd: 'FF',
a: '19.5',
b: '-12.34',
c: '5.0',
spon: 'CYA' }

数据字段看起来不错,到目前为止文件已正确处理,但是 => 对象“obj”将仅包含最后一个数据集(名称:Berry),因为它在每一行之后都会被重写。我通过切断线仔细检查

console.log(obj);

从 readAndFilter.on('line', ... block 并将其插入到 'close' block 中:

[...]
readAndFilter.on('line', (line) => {
if ( line.match( /#/ ) ) {
fields = line.split( '#' ).slice();
obj.name = fields[0].trim();
obj.sec = fields[1].trim();
obj.ter = fields[2].trim();
obj.wrd = fields[3].trim();
obj.a = fields[4].trim();
obj.b = fields[5].trim();
obj.c = fields[6].trim();
obj.spon = fields[7].trim();

// let jsonView = JSON.stringify(obj);
// arr.push(obj);
}
});

readAndFilter.on('close', function() {
console.log(obj);
return arr;
});
[...]

产生的输出是:

 { name: 'Berry',
sec: '19',
ter: '22',
wrd: 'FF',
a: '19.5',
b: '-12.34',
c: '5.0',
spon: 'CYA' }

这不能用作查找表,我需要一个数组中的所有行,以便稍后在查找例程中访问它们。所以我尝试使用以下代码将每个对象添加到一个数组中:

    [...]
readAndFilter.on('line', (line) => {
if ( line.match( /#/ ) ) {
fields = line.split( '#' ).slice();
obj.name = fields[0].trim();
obj.sec = fields[1].trim();
obj.ter = fields[2].trim();
obj.wrd = fields[3].trim();
obj.a = fields[4].trim();
obj.b = fields[5].trim();
obj.c = fields[6].trim();
obj.spon = fields[7].trim();

// let jsonView = JSON.stringify(obj);
arr.push(obj);
}
});

readAndFilter.on('close', function() {
console.log(arr);
return arr;
});
[...]

现在我得到一个包含三个对象的数组,但只显示最后一个数据集名称:Berry again

 [ { name: 'Berry',
sec: '19',
ter: '22',
wrd: 'FF',
a: '19.5',
b: '-12.34',
c: '5.0',
spon: 'CYA' },
{ name: 'Berry',
sec: '19',
ter: '22',
wrd: 'FF',
a: '19.5',
b: '-12.34',
c: '5.0',
spon: 'CYA' },
{ name: 'Berry',
sec: '19',
ter: '22',
wrd: 'FF',
a: '19.5',
b: '-12.34',
c: '5.0',
spon: 'CYA' } ]

我什至尝试使用 concat 和许多其他变体。我到底做错了什么?我使用 readline/line-by-line 技术的方法是否完全错误,我应该改用 fs.readFileSync 吗?我也试过了,这是我使用 fs.readFileSync 的方法:

            function readAndFilter () {
var fields;
var obj = new Object;
var arr = new Array;
var data = fs.readFileSync('test.in', 'utf8').replace(/\r\n/g,'\n').split('\n').filter(/./.test, /\#/)
/*
if ( data.match( /#/ ) ) {
fields = data.split( '#' ).slice();
obj.name = fields[0].trim();
obj.cqz = fields[1].trim();
obj.itu = fields[2].trim();
obj.cont = fields[3].trim();
obj.lng = fields[4].trim();
obj.lat = fields[5].trim();
obj.tz = fields[6].trim();
obj.pfx = fields[7].trim();
};
*/
console.log(typeof data + "\n" + data);
}

一旦我开始使用 .split('\n') ,可变数据就是 typeof 对象,因此我无法使用我的以下 if 子句。它失败了,因为它只适用于字符串。也许我完全指向错误的方向而且它更简单?最终目标是:我想根据此查找表检查类似 "Apple" 的搜索字符串并检索适当的值(name、sec、ter、b 或其中任何一个)。

我真的很感谢任何有帮助的回答或提示。请耐心和我说实话:我真的试了很多!感谢大家。

最佳答案

首先,欢迎来到 SO,并称赞你的重点和详尽的问题。干得好!

您的流解决方案无法按预期工作的原因是因为它是异步的,因此您试图在结果实际存在之前访问它。查看我们的 classic thread了解更多相关信息。

但是,为了简单起见,我建议坚持使用 readFileSync 解决方案。一般来说,出于性能原因,不建议在 node.js 中使用同步功能,但考虑到文件很小(3000 行),应该不会有太大影响。

一旦你阅读了文件,解析就可以像这样完成:

let text = fs.readFileSync('test.in', 'utf8');

let result = [];

for (let line of text.trim().split('\n')) {

if (!line.includes('#'))
continue;

let s = line.trim().split(/[#\s]+/g);

result.push({
name: s[0],
sec: s[1],
ter: s[2],
wrd: s[3],
a: s[4],
b: s[5],
c: s[6],
spon: s[7],
});
}


console.log(result)

关于JavaScript - 将空格分隔的文本文件读入数组并用作查找表,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/56619678/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com