简体   繁体   English

按值减少一个数组

[英]Reduce an Array of Arrays by value

I have an array of arrays similar to the structure below. 我有一个类似于下面结构的数组数组。 I am trying to reduce the array as efficiently as possible based on the Company Name (ex. Company A). 我试图根据公司名称(例如公司A)尽可能有效地减少阵列。 So basically, where the company names are the same, combine the inner array so that the numbers in each position get added to the matching array's numbers in the corresponding position. 因此,基本上,在公司名称相同的情况下,请组合内部数组,以便将每个位置的数字添加到对应位置的匹配数组的数字中。 Also if one of the arrays has a missing email or phone, take the email or phone position that has a value. 另外,如果其中一个阵列缺少电子邮件或电话,请采用具有价值的电子邮件或电话位置。 The resultArray at the bottom shows the result I am trying to achieve. 底部的resultArray显示了我要达到的结果。

*Note - I don't know the length of numbers following a company. *注意-我不知道跟进公司的电话号码的长度。 The length is dynamically set, but the length of each inner array will always be the same. 长度是动态设置的,但是每个内部数组的长度将始终相同。 So sometimes all the innerArray's are 6 values, other times they could be 20 values in length. 所以有时候所有的innerArray都是6个值,有时它们的长度可能是20个值。

var array = [
    [Company A, A-Email, A-Phone, 2, 5, 10],
    [Company A, A-Email, , 1, 10, 7],
    [Company A, , A-Phone, 3, 2, 4],
    [Company B, B-Email, , 1, 10, 7],
    [Company B, B-Email, B-Phone, 5, 10, 8],
    [Company C, C-Email, C-Phone, 3, 2, 1]
  ]
var resultArray = [
    [Company A, A-Email, A-Phone, 6, 17, 21],
    [Company B, B-Email, B-Phone, 6, 20, 15],
    [Company C, C-Email, C-Phone, 3, 2, 1]
  ]

So originally I was trying something like this because the array had already been sorted by company name: 所以最初我尝试这样的事情,因为该数组已经按公司名称排序:

for (var i = 0; i < array.length - 1; i++) {
  var firstArray = array[i]
  var nextArray = array[i + 1]
  if (nextArray[0] == firstArray[0]) {
    for (var t = 3; t <= firstArray.length; t++) {
      firstArray[t] = firstArray[t] + nextArray[t]

    }
    resultArray.push(firstArray);
} else {continue;}

I have a large set of data and doing it this way was really operation heavy and my function timed out so I'm not completely sure if it even worked. 我有大量数据,以这种方式进行操作确实操作繁重,并且我的功能超时,因此我不确定是否能正常工作。 I started to try to do a reduce method with a hash table but I couldn't quite figure it out. 我开始尝试对哈希表执行reduce方法,但是我不太清楚。 Any idea's on how to do this most efficiently? 关于如何最有效地执行此操作的任何想法?

Also I can't use jQuery, so purely vanilla javascript please. 另外我不能使用jQuery,所以请纯香草javascript。

You can use ES6 reduce to summarize the array into an object. 您可以使用ES6 reduce将数组汇总为一个对象。 And use Object.values to convert the object into an array. 并使用Object.values将对象转换为数组。

Note: Fiddle does not (currently) working. 注意:小提琴(目前)无法运作。 So you might need to test it on your browser. 因此,您可能需要在浏览器上对其进行测试。

 var array=[['Company A','A-Email','A-Phone',2,5,10],['Company A','A-Email',,1,10,7],['Company A',,'A-Phone',3,2,4],['Company B','B-Email',,1,10,7],['Company B','B-Email','B-Phone',5,10,8],['Company C','C-Email','C-Phone',3,2,1]]; var resultArray = Object.values(array.reduce((c, v) => { c[v[0]] = c[v[0]] || [v[0], null, null].concat(new Array(v.length - 3).fill(0)); c[v[0]][1] = c[v[0]][1] || v[1]; //Update Email c[v[0]][2] = c[v[0]][2] || v[2]; //Update Phone //Loop thru the numbers and add for (var i = 3; i < v.length; i++) c[v[0]][i] += ( v[i] || 0 ); return c; }, {})); console.log(resultArray); 

Hash tables would be the correct approach (assuming 'Company A' etc are strings; otherwise it's a Map). 哈希表是正确的方法(假设“ Company A”等是字符串;否则为Map)。

var companies = {};
for ( var i = 0; i < array.length; i++ ) {
    var item = array[ i ];
    var name = item[ 0 ];
    var phone = item[ 1 ];
    var num1 = item[ 2 ];
    var num2 = item[ 3 ];
    var num3 = item[ 4 ];
    if ( companies[ name ] ) {
        var record = companies[ name ];
        record[ 1 ] = record[ 1 ] || email;
        record[ 2 ] = record[ 2 ] || phone;
        record[ 2 ] += num1;
        record[ 3 ] += num2;
        record[ 4 ] += num3;
    } else {
        companies[ name ] = [ name, email, phone, num1, num2, num3 ]
    }
}
var resultArray = Object.values( companies );

You can try something like below. 您可以尝试以下类似方法。 The main point is to use reduce() to get an object full of correct data then flatten it back into arrays using Object.values() . 主要要点是使用reduce()获取充满正确数据的对象,然后使用Object.values()将其展平为数组。

 //initial data var data = [ ['Company A', 'A - Email', 'A - Phone', 2, 5, 10], ['Company A', 'A - Email', , 1, 10, 7], ['Company A', , 'A - Phone', 3, 2, 4], ['Company B', 'B - Email', , 1, 10, 7], ['Company B', 'B - Email', 'B - Phone', 5, 10, 8], ['Company C', 'C - Email', 'C - Phone', 3, 2, 1] ]; //reduce function to organize data var reducer = function(accumulator, currentValue, currentIdx) { var [companyId, email, phone, i, j, k] = currentValue; accumulator[companyId] = { email: !accumulator[companyId] ? email : !accumulator[companyId].email ? email : accumulator[companyId].email, phone: !accumulator[companyId] ? phone : !accumulator[companyId].phone ? phone : accumulator[companyId].phone, i: (accumulator[companyId] ? accumulator[companyId].i : 0) + i, j: (accumulator[companyId] ? accumulator[companyId].j : 0) + j, k: (accumulator[companyId] ? accumulator[companyId].k : 0) + k } return accumulator; } var rawData = data.reduce(reducer, {}); //organize data back into array of arrays var formattedData = []; for (key in rawData) { formattedData.push([key].concat(Object.values(rawData[key]))); } console.log(formattedData); 

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM