1

我正在尝试使用 Javascript 在 CSV 文件中查找一个值并返回它的对应值(基本上是 VLOOKUP 在 Excel 中的作用)

我已经能够单独遵循一些将 CSV 数据拉入数组的示例,并且我已经看到了一些在数组中查找数据的示例 - 但对于我的生活,我无法弄清楚如何让两者都工作.

例如,CSV 文件stations.csv 具有以下数据:

mac,name
69167f276e9g,LINE1
69167f276e9f,LINE2

我想要做的是从 CSV 中查找 'mac' 值,并返回相应的 'name' 值。

因此,如果我寻找“69167f276e9f”,我想取回 LINE2 的值。

[编辑:使用 MauriceNino 的建议添加我尝试过的代码 - 但出现错误Uncaught TypeError: Cannot read property '1' of undefined at the line 'return result[1];' ]:

$.ajax('stations.csv').done(function(data) {

  const lookup = (arr, mac) => {
    let twoDimArr = dataArr.map(el => el.split(',')); // map it to array of arrays of strings (data)
    let result = twoDimArr.filter(el => el[0] == mac)[0]; // Get the first element where the mac matches the first element in the array
    return result[1]; // Return the second element in the array
};

    let dataArr = data.split('\n');
    dataArr .shift(); // Remove the first array element (The header)

    let resultMac = lookup(dataArr, "69167f276e9f");

    console.log(resultMac);

})
4

4 回答 4

1

这是一个可能的解决方案:

  • 它首先从您的数据创建一个二维数组
  • 然后它搜索具有指定 mac 作为第一个值的第一个元素
  • 然后它返回该数组的第二个元素

const data = `mac,name
69167f276e9g,LINE1
69167f276e9f,LINE2`;

const lookup = (arr, mac) => {
    let twoDimArr = dataArr.map(el => el.split(',')); // map it to array of arrays of strings (data)
    let result = twoDimArr.filter(el => el[0] == mac)[0]; // Get the first element where the mac matches the first element in the array
    return result[1]; // Return the second element in the array
}

let dataArr = data.split('\n');
dataArr .shift(); // Remove the first array element (The header)

let resultMac = lookup(dataArr, '69167f276e9f');

console.log(resultMac);

于 2019-07-31T09:06:33.717 回答
0

首先将 CSV 转换为对象数组。
比使用Array.prototype.find()在该数组中查找属性值与所需字符串匹配的对象。

const csv2array = (csv, dlm = ',') => {
  const [heads, ...lines] = csv.split('\n'), th = heads.split(dlm);
  return lines.map(l => l.split(dlm).reduce((o, c, i) => (o[th[i]] = c.trim(), o), {}));
}
const findInCSV = (csv, p, v) => csv2array(csv).find(k => k[p] === v);


// Getting stuff:

const myCSV = `mac,name
69167f276e9g,LINE1
69167f276e9f,LINE2`;

console.log(findInCSV(myCSV, 'mac', '69167f276e9g'))      // Get entire object by knowing the mac
console.log(findInCSV(myCSV, 'mac', '69167f276e9g').name) // Get name knowing the mac 
console.log(findInCSV(myCSV, 'name', 'LINE1'))            // Get entire object by knowing the name 
console.log(findInCSV(myCSV, 'name', 'LINE1').mac)        // Get mac knowing the name

于 2019-07-31T09:38:09.780 回答
0

我刚刚写完一个几乎完全相同的脚本。我在那里所做的是使用readlinefs库流式传输 csv 文件:

csvStream = readline.createInterface({
        input: fs.createReadStream(filePath);
});

然后,我使用流库的line事件手动解析了 csv 的每一行:readline

decompressedStream.on('line', (line) =>

我的 csv 有一种特殊的结构,所以我不得不手动解析和对值进行一些修改,但基本上这个想法是将你得到的字符串拆分为'line'使用line.split和你的分隔符,然后将每个值推送到一个单元格数组。你得到的是一个数组,其中的每个单元格代表 csv 行中的一个值,然后你可以将它推送到另一个代表整个 csv 的大数组,其中每个单元格代表一条线。

之后,您可以使用该close事件来了解流何时结束:

decompressedStream.on('close', () =>

然后只需使用array.find整个 csv 数组来查找您要查找的值即可:

let res = csvArray.find(val => val[0] == curMac)

接着

return res[1]

编辑:我刚刚看到 MauriceNino 的回答,这与我的非常相似。注意差异:

  1. 在他的回答中,他只使用分隔符进行拆分,在我的情况下,您可以选择在将数据推送到每行的数组之前添加更多计算或修改,并且还考虑特殊情况,例如当您将分隔符包含在值中时被...围绕 ””。这就是为什么我需要使用流方法。

  2. 他的方法非常适合小文件,但将超大文件直接加载到内存可能会很糟糕。我正在处理 15GB 的 csv 文件,所以我不得不使用流。这样我可以加载几行,处理它们并转储我的数据,然后再次加载大量行。

看起来,他的逻辑更适合你的情况,但我不知道你的程序的整个流程或目的,所以我会在这里留下我的答案,让你决定哪个更适合你:)

于 2019-07-31T09:18:11.377 回答
-1

听起来你需要一本字典,例如:

var myMappings = {
'69167f276e9f': 'LINE1',
'69167f276e9g': 'LINE2'
};

var myVal = myMappings['69167f276e9g'];

alert(myVal); // prints LINE2
于 2019-07-31T09:14:06.173 回答