Aditya Raj
Aditya Raj

Reputation: 337

How to spread an array without using a spread operator?

Is there a way through functions or array methods to spread an array without the spread operator. I was solving Algo challenges on FCC and was just curious about this.

function uniteUnique(arr) {
  var args = [].slice.call(arguments);
  var newArr = [];
  args.forEach(arr => newArr.push(...arr));
  return newArr.reduce((array, num) => {
    if(!array.includes(num)) {
      array.push(num);
    }
    return array;
  }, []);
}

Upvotes: 1

Views: 3676

Answers (3)

Thomas
Thomas

Reputation: 12657

var args = [].slice.call(arguments);
var newArr = [];
args.forEach(arr => newArr.push(...arr));

this part of your code is just flattening the arguments by one level, and can also be written as

var newArr  = [].concat.apply([], arguments);

and

return newArr.reduce((array, num) => {
   if(!array.includes(num)) {
     array.push(num);
   }
   return array;
}, []);

is returning a version of that without duplicates. Wich can also be achieved differently

//adding that, because it's so much simpler than your reduce
return [...new Set(newArr)]; 
return Array.from(new Set(newArr)); 

//or
return newArr.filter(function(v,i){ return newArr.indexOf(v) === i });

and the whole thing

function uniteUnique( /*...arrays*/ ) {
  return [].concat.apply([], arguments)
    .filter(function(v, i, a) {
      return a.indexOf(v) === i
    });
}

console.log(uniteUnique(
  1, 
  [2, 3, 4], 
  2, 
  [3, 5], 
  [2, 4, 6, 8], 
  8, 
  [1, 3, 5, 7, 9]
));
.as-console-wrapper{top:0;max-height:100%!important}


If you want to flatten by multiple (all) levels, you can do this like

//reusable helper
function _flatten(into, value){
  if(Array.isArray(value)) 
    return value.reduce(_flatten, into);

  into.push(value);
  return into;
}

function _unique(v,i,a){ 
  return a.indexOf(v) === i;
}

function uniteUnique( /*...arrays*/ ) {
  return _flatten([], [].slice.call(arguments))
    .filter(_unique);
}

or the all-in-one solution

function uniteUnique( /*...arrays*/ ) {
  return (function _recursive(into, value){
    if(Array.isArray(value)) 
      return value.reduce(_recursive, into);

    if(into.indexOf(value) === -1) into.push(value);
    return into;
  })([], [].slice.call(arguments));
}

Upvotes: 1

pwolaq
pwolaq

Reputation: 6381

const newArray = [...oldArray];

will produce identical output as using Array.prototype.concat:

const newArray = [].concat(oldArray)

if you want to merge all arrays into one then you can do it with Array.prototype.reduce:

const newArray = args.reduce((acc, arr) => acc.concat(arr), [])

Upvotes: 0

zero298
zero298

Reputation: 26909

Use Function.prototype.apply(). Consider this article about emulating spread with apply(): Using 'apply' to Emulate JavaScript's Upcoming Spread Operator.

function uniteUnique(arr) {
  var args = [].slice.call(arguments);
  var newArr = [];

  args.forEach(arr => Array.prototype.push.apply(newArr, arr));

  return newArr.reduce((array, num) => {
    if(!array.includes(num)) {
      array.push(num);
    }
    return array;
  }, []);
}

Upvotes: -1

Related Questions