我正在尝试使用JavaScript在CSV文件中查找一个值并返回其相应的值(基本上是Vlookup在Excel中所做的(
我已经能够分别遵循一些将CSV数据拉入数组的示例,而且我已经看到了一些在数组中查找数据的示例 - 但是对于我的一生,我不知道如何弄清楚如何让两个工作。
例如,csv文件stations.csv具有以下数据:
mac,name
69167f276e9g,LINE1
69167f276e9f,LINE2
我想做的就是从CSV查找" Mac"值,然后返回相应的"名称"值。
所以,如果我寻找'69167f276e9f'我想回到值line2。
[edit:添加我尝试使用Mauricenino的建议的代码 - 但是获得错误 undfult typeError:无法在line '返回结果[1]上读取未定义的的属性'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);
})
这是一个可能的解决方案:
- 它首先从您的数据中创建一个二维数组
- 然后它搜索将指定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);
我刚刚写完一个脚本几乎完全相同的脚本。我在那做的是我使用readline
和fs
库流了CSV文件:
csvStream = readline.createInterface({
input: fs.createReadStream(filePath);
});
然后,我使用readline
流库的line
事件手动解析CSV的每一行:
decompressedStream.on('line', (line) =>
我的CSV具有特殊的结构,因此我必须对值进行手动解析和对值进行一些修改,但是基本上,想法将您使用line.split
和您的分配器分配为"行",然后推动每个值到阵列中的单元格。您得到的是一个数组,其中每个单元格代表CSV线中的一个值,然后您可以将其推到另一个大数组,该数组代表整个CSV,并且每个单元格代表一条线。
之后,您可以使用close
事件知道流何时结束:
decompressedStream.on('close', () =>
,然后是使用array.find
整个CSV数组来找到您寻找的值:
let res = csvArray.find(val => val[0] == curMac)
,然后
return res[1]
编辑:我刚刚看到了毛里切尼诺的答案,这与我的回答非常相似。注意差异:
在他的回答中,他仅使用特定器进行分割,在我的情况下,您可以选择在将数据推到每行的数组之前,对数据进行更多的计算或修改,并考虑到特殊情况,例如在被"包围的值包围。那就是为什么我需要使用流方法。
他的方法非常适合小文件,但是将极大的文件直接加载到内存可能是不好的。我正在处理15GB CSV文件,因此我必须使用该流。这样,我可以加载几行,对其进行处理并转储我的数据,然后再次加载一条线。
看来,他的逻辑更适合您的情况,但是我不知道您程序的全部流程或目的,因此我将在这里留在这里,以便您决定哪种更适合您:(
首先将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
听起来您需要字典,例如:
var myMappings = {
'69167f276e9f': 'LINE1',
'69167f276e9g': 'LINE2'
};
var myVal = myMappings['69167f276e9g'];
alert(myVal); // prints LINE2