简体   繁体   中英

finding the difference in multiple arrays. using reduce

I am trying to recreate the underscore js function difference using reduce. Difference takes in multiple arrays and returns all values that are similiar to the first array. so [1,2],[2,3],[1,3] should spit out [1,2,2,1].

I was thinking of looping through each of my subarray(rest) and if the value of my sub elements has an index in my first array then I will push that element onto my accumulator value(which is an empty array).

Some reason I do not get my intended output where I was expecting [1,2,3,2,1,2]. instead I am getting [ [ 1, 2 ], [ 2, 4 ], [ 1, 2 ] ]. Can anyone help me with this rewrite using reduce. Thanks.

function difference(arrays){
var arrayed=Array.prototype.slice.call(arguments);
var first=arrayed[0];
var rest=arrayed.slice(1);

return reduce(first,function(acc,cur){
  forEach(rest,function(sub){
    if (sub.indexOf(cur)>-1){
      acc.push(sub);
    }});
    return acc;
  },[]);
}

console.log(difference([1,2,3],[2,4],[1,2],[4,5]));

i know the way im calling forEach is different but it is because my own version of forEach accepts two arguments.

Here's a solution :

function difference(arrays){
  var arrayed = Array.prototype.slice.call(arguments);
  var first = arrayed.splice(0,1)[0]; // edit, thanks robG
  var tmp = [];

  return arrayed.reduce(function(acc, arr) {
    return acc.concat(arr.filter(function(el) {
      return first.includes(el);
    }));
  }, first);
}

console.log(difference([1,2,3],[2,4],[1,2],[4,5]));

Use the javascript reduce method on the 'rest' array, makes the first array be the default value of the accumulator, filter the arrays with the first one and concat the result to your accumulator.

Hope it helps,
best regards

Could try this

function difference(arrays){
  var arrayed=Array.prototype.slice.call(arguments);
  var first=arrayed[0];
  var rest=arrayed.slice(1);

  return first.concat(rest.reduce(function(acc, cur, curIndex, array){
    first.forEach(function(eachEle){
      if(cur.indexOf(eachEle) > -1 )
        acc.push(cur[cur.indexOf(eachEle)]);
    });
    return acc;
  }, []));
}

console.log(difference([1,2,3],[2,4],[1,2],[4,5]));

As for your previous question , you need to call array methods on arrays, not pass them as parameters so not

return reduce(first,function(acc,cur){...})

but

return first.reduce(function(acc,cur){...});

In your function:

var first=arrayed[0];
var rest=arrayed.slice(1);

can be replaced with one step using splice:

var first = arrayed.splice(0, 1)

and use arrayed instead of rest . But there's no need for that anyway. If no accumulator is provided, then the first value is used, so (with some renaming of variables):

 function difference(){ var args = Array.prototype.slice.call(arguments); return args.reduce(function(acc, cur){ cur.forEach(function(value){ if (acc.includes(value)){ acc.push(value); } }); return acc; }); } console.log(difference([1,2,3],[2,4],[1,2],[4,5])); 

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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