1

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;
  }, []);
}
3
  • You're too curious. / Why do you want to not using them? / What about eval? Unobservable behavior. Commented Feb 6, 2018 at 14:48
  • please add some data to test the function. what do you expect? Commented Feb 6, 2018 at 14:50
  • If you didn't use spread syntax, it wouldn't be called spreading any more… what do you want to do? Commented Feb 6, 2018 at 15:08

3 Answers 3

1
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));
}
Sign up to request clarification or add additional context in comments.

Comments

1
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), [])

Comments

-1

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;
  }, []);
}

3 Comments

@user202729 I mixed up apply and call at the very start of my answer.
"question"? "answer"?
@user202729 Yes, I also mixed up "answer" with "question" at the start of my comment. My morning is not starting well.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.