2017-04-26 118 views
1

我有一个CSV,我通过csv加载到内存中,这将返回一个对象数组,其中的每一行数据都带有键值对,其中键是列,值是与该栏。因此:基于特定的列用Javascript对数据进行分组

[{col1: 'id1', col2: '123', col3: '12/01/12'}, 
{col1: 'id1', col2: '100', col3: '12/01/12'}, 
{col1: 'id2', col2: '-100', col3: '12/01/12'}, 
{col1: 'id2', col2: '123', col3: '13/01/12'}] 

我希望能够做的是组数据使得例如用于ID1上的数据12年12月1日的总和col2列的是什么。或者,对于id2,2012年12月12日至2012年1月13日期间col2的值有什么区别。

相当新的(1周)JS,所以任何意见,将不胜感激。

+0

我建议你看看一个名为lodash(下划线)的库。它帮助与js的数组相关的功能 – user5328504

+0

可能重复[什么是最有效的方法来groupby一个JavaScript数组的对象?](http://stackoverflow.com/questions/14446511/what-is-the-most-有效的方法到对象上的一个javascript对象) –

回答

1

对于分组,我使用Array过滤方法。如果您希望在已过滤的数组中包含一个数组元素,它将接收一个应该返回true的函数。因此,为了得到这COL1是“ID1”和COL3是'12/01/12' 行,你会怎么做:

var data = [{col1: 'id1', col2: '123', col3: '12/01/12'}, 
      {col1: 'id1', col2: '100', col3: '12/01/12'}, 
      {col1: 'id2', col2: '-100', col3: '12/01/12'}, 
      {col1: 'id2', col2: '123', col3: '13/01/12'}]; 

var grouped = data.filter( function(row) { 
           return row.col3 == '12/01/12' && row.col1 == 'id1'; 
          }); 

对于一个组内总结一列,可以使用Array减少方法。它将第一个参数作为一个“减少”函数,将数组元素减少为单个值。它以可选的第二个参数作为起始值。还原函数必须有两个参数。在第一次迭代中,第一个参数是指定的起始值,在后续迭代中,它是前一次迭代中函数的返回值。还原函数的第二个参数是数组的一个元素。所以总结您的分组数据的第二列,你会怎么做:

var sumOfGrouped = grouped.reduce(function(sumSoFar, row) { return sumSoFar + parseInt(row.col2) }, 0); 

看看其他阵列的方法,你会发现其他人可能是你这取决于你想要做什么有用的。

+0

谢谢 - 这正如我所希望的那样工作,将需要使其更通用,但很确定这不会是一个问题。 我有一个关于reduce函数的问题,0的目的是什么,因为包括它给了我正确的总结,就好像我不包含它一样,我得到了一个打印出来的所有值,如:123100-10。 我阅读文档,它说它设置初始值,但这似乎并不能解释我的结果。 再次感谢您 – GoodCat

+0

0是减少结果的初始值。因此,在上面的示例中,在reduce的第一次迭代中,sumSoFar为0(指定为第二个参数以减少),并将行分组为[0]。在该迭代中,该函数返回0 + 123 = 123,该值在第二次迭代中成为sumSoFar的值,其中row = grouped [1]。在该迭代中,该函数返回123 + 100 = 223,这是结果。如果你省略零,那么在reduce的第一次迭代中,sumSoFar被分组[0]并且行被分组[1] ... – cjg

+0

...当我删除零并按原样运行函数时,我得到' [对象对象] 100'。这是因为函数返回了sumSoFar + parseInt(row.col2)= groupped [0] + parseInt(grouped [1] .col2]。grouped [0]是一个对象,但它被转换为一个字符串('[object Object ]')和+被视为字符串连接运算符,因此grouped [1] .col2被转换回一个字符串并连接到'[object Object]'如果你改变函数返回sumSoFar.col2 + parseInt(row .col2),那么我希望你得到的结果,出于类似的原因... – cjg

1

我创建了一个函数,它的参数是一个String,表示列名。在这个例子中,我传递了"col1" - ID列。

该函数创建一个空对象。它遍历数据数组并检查是否已存储具有相同ID的对象。如果没有,我创建一个新的属性,它与ID的名称相同,并为其分配一个空数组。

该空数组将包含具有相同ID的对象。

var data = [ 
 
    {col1: 'id1', col2: '123', col3: '12/01/12'}, 
 
    {col1: 'id1', col2: '100', col3: '12/01/12'}, 
 
    {col1: 'id2', col2: '-100', col3: '12/01/12'}, 
 
    {col1: 'id2', col2: '123', col3: '13/01/12'} 
 
]; 
 

 
function sortData(columnName) { 
 
    var sortedData = {}; 
 

 
    for (var i = 0; i < data.length; i++) { 
 
     var object = data[i]; 
 

 
     if (Object.keys(sortedData).indexOf(object[columnName]) === -1) { 
 
      sortedData[object[columnName]] = []; 
 
     } 
 

 
     sortedData[object[columnName]].push(object); 
 
    } 
 
    
 
    return sortedData; 
 
} 
 

 
console.log(sortData("col1"));

+1

谢谢 - 这提供了一个有用的起点,我可能会将它与cjg提供的解决方案一起使用,但他提供了我需要的确切结果 – GoodCat

相关问题