2

I'm trying to achieve to write an array function with the use of reduce and find helpers that returns an array of unique numbers.

var numbers = [1, 1, 2, 3, 4, 4];
// function should return [1, 2, 3, 4]

function unique(array) {
  array.reduce((uniqueArray, number) => {
    if (uniqueArray.indexOf(find(array.number))) {
      uniqueArray.push(array.number);
    }
    return uniqueArray;
  }, []);
}
console.log(unique(numbers));
// undefined 
// undefined

When running this code I get

undefined

twice in Browser Javascript console.

StandardNerd
  • 4,093
  • 9
  • 46
  • 77

4 Answers4

4

You need a return statment.

return array.reduce((uniqueArray // ...
// ^^^

And some better find method with Array.indexOf

function unique(array) {
    return array.reduce((uniqueArray, number) => {
        if (uniqueArray.indexOf(number) === -1) {
            uniqueArray.push(number);
        }
        return uniqueArray;
    }, []);
}

var numbers = [1, 1, 2, 3, 4, 4];
console.log(unique(numbers));

And now with Set and spread syntax ... for collecting the items in a new array.

function unique(array) {
    return [... new Set(array)];
}

var numbers = [1, 1, 2, 3, 4, 4];
console.log(unique(numbers));
Nina Scholz
  • 376,160
  • 25
  • 347
  • 392
  • includes is fine, but it does not work in edge, actually. – Nina Scholz Jan 09 '17 at 14:45
  • your `find` does not work on arrays that contain a `0`. You should use `some` or simply `includes`. – Bergi Jan 09 '17 at 15:05
  • @Bergi, then indexOf is better, at least as find. – Nina Scholz Jan 09 '17 at 15:11
  • Yes indeed. An alternative (as long as the array does only contain numbers) is `….find(…) != null` – Bergi Jan 09 '17 at 15:26
  • @Bergi, if not found, then [`find`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/find) returns `undefined`, but if `undefined` is a value, then it does not work. – Nina Scholz Jan 09 '17 at 15:29
  • 1
    That's what I meant by "if the array does only contain numbers" (which `undefined` is not) – Bergi Jan 09 '17 at 15:38
3

The reasons for the errors are explained in previous answers. So I just adding an alternate method with Array#filter method.

var numbers = [1, 1, 2, 3, 4, 4];
// function should return [1, 2, 3, 4]

function unique(array) {
  return array.filter(function(v, i, arr) {
    // compare index with first element index
    return i == arr.indexOf(v);
  })
}
console.log(unique(numbers));

With ES6 arrow function.

var numbers = [1, 1, 2, 3, 4, 4];
// function should return [1, 2, 3, 4]

function unique(array) {
  return array.filter((v, i, arr) => i == arr.indexOf(v))
}
console.log(unique(numbers));

UPDATE : With a reference object instead of checking the index.

var numbers = [1, 1, 2, 3, 4, 4],
  ref = {};


function unique(array) {
  return array.filter(function(v) {
    if (!(v in ref)) {
      ref[v] = true;
      return true;
    }
    return false;
  })
}
console.log(unique(numbers));
Pranav C Balan
  • 113,687
  • 23
  • 165
  • 188
2

You have few errors. First you need to return value from your function and also to check if element is already in uniqueArray you can use indexOf() == -1.

var numbers = [1, 1, 2, 3, 4, 4];

function unique(array) {
  return array.reduce((uniqueArray, number) => {
    if (uniqueArray.indexOf(number) == -1) uniqueArray.push(number)
    return uniqueArray;
  }, []);
}
console.log(unique(numbers));

With ES6/7 you can use includes() and arrow functions like this.

var numbers = [1, 1, 2, 3, 4, 4];

function unique(arr) {
  return arr.reduce((r, n) => (!r.includes(n) ? r.push(n) : 1) && r , []);
}
console.log(unique(numbers));
Nenad Vracar
  • 118,580
  • 15
  • 151
  • 176
0

You can always use Array.includes.

function SillyFunctionName(array) {
    "use strict";

    var uniqueArray = [];

    for (var i = 0; i < array.length; i++) {
        if (uniqueArray.includes(array[i])) {
            break;
        } else {
            uniqueArray.push(array[i]);
        }
    }

    return uniqueArray;
}
Joshua
  • 648
  • 7
  • 18