22

在我的 CouchDB reduce 函数中,我需要将项目列表减少为唯一的项目。

注意:在这种情况下,可以有一个列表,它将是少量字符串类型的项目。

我目前的方法是设置一个对象的键,然后返回该对象的键,因为代码不能使用_.uniq例如。

我想找到一种比这更优雅的拼写方式。

function(keys, values, rereduce) {
  // values is a Array of Arrays
  values = Array.concat.apply(null, values);
  var uniq = {};
  values.forEach(function(item) { uniq[item] = true; });
  return Object.keys(uniq);
}
4

9 回答 9

47

最好的方法似乎是使用 ES6 和 Set。根据小提琴,单行且比上面更快*

    
const myList = [1,4,5,1,2,4,5,6,7];
const unique = [...new Set(myList)];
    
console.log(unique);

*在野生动物园测试

于 2018-09-29T07:36:47.340 回答
31

2021年答案:

const unique = (arr) => [...new Set(arr)];
unique([1, 2, 2, 3, 4, 4, 5, 1]); // [1, 2, 3, 4, 5]

在这里,您只需从给定数组创建一个集合,然后将其转换回数组。我测量了性能,现在它几乎比我之前发布的旧答案中提出的方法快两倍。而且,它只是一个单行。

更新的小提琴

旧答案仅供记录:

通常,您使用的方法是一个好主意。但我可以提出一个解决方案,使算法更快。

function unique(arr) {
    var u = {}, a = [];
    for(var i = 0, l = arr.length; i < l; ++i){
        if(!u.hasOwnProperty(arr[i])) {
            a.push(arr[i]);
            u[arr[i]] = 1;
        }
    }
    return a;
}

如您所见,我们这里只有一个循环。

我做了一个例子来测试你和我的解决方案。尝试玩它。

于 2012-08-11T02:59:05.063 回答
10

适用于小列表的替代方法是模仿 Unix 命令行方法sort | uniq

    function unique(a) {
        return a.sort().filter(function(value, index, array) {
            return (index === 0) || (value !== array[index-1]);
        });
    }

此函数对参数进行排序,然后过滤结果以省略与其前任相同的任何项目。

基于键的方法很好,并且对于大量项目(将 n 个项目插入哈希表的 O(n) 与对数组排序的 O(n log n) 相比)具有更好的性能特征。但是,这在小型列表中不太可能引起注意。此外,在此版本中,您可以根据需要修改它以使用不同的排序或相等函数;使用哈希键,您会被 JavaScript 的键相等概念所困扰。

于 2015-07-01T10:37:59.493 回答
8

这应该适用于任何东西,而不仅仅是字符串:

export const getUniqueList =  (a: Array<any>) : Array<any> => {

  const set = new Set<any>();

  for(let v of a){
      set.add(v);
  }

  return Array.from(set);

};

以上可以简化为:

export const getUniqueValues = (a: Array<any>) => {
   return Array.from(new Set(a));
};

:)

于 2018-08-12T20:08:21.160 回答
0

这是一个老问题,我知道。但是,它位于一些谷歌搜索的顶部,所以我想补充一点,您可以使用以下方法组合来自 @RobHague 和 @EugeneNaydenov 的答案:

function unique(arr) {
  const u = {};
  return arr.filter((v) => {
    return u[v] = !u.hasOwnProperty(v);
  });
};

您还可以通过添加以下内容来忽略未定义的值(通常很方便):

function unique(arr) {
  const u = {};
  return arr.filter((v) => {
    return u[v] = (v !== undefined && !u.hasOwnProperty(v));
  });
};

您可以在此处使用此解决方案:https ://jsfiddle.net/s8d14v5n/

于 2017-07-21T18:10:01.773 回答
0

如果您输入整数参数 (uniq([1,2,3]) => ['1','2','3'],则使用 Object.keys 将为您提供字符串。这是 Array.reduce 的一个:

function uniq(list) {
    return list.reduce((acc, d) => acc.includes(d) ? acc : acc.concat(d), []);
}
于 2017-08-05T16:20:17.897 回答
0

我发现其他答案相当复杂,因为我看不到任何收益。

我们可以使用 Array 的indexOf方法在推送之前验证其中是否存在项目:

const duplicated_values = ['one', 'one', 'one', 'one', 'two', 'three', 'three', 'four'];
const unique_list = [];

duplicated_values.forEach(value => {
  if (unique_list.indexOf(value) === -1) {
    unique_list.push(value);
  }
});

console.log(unique_list);

这也适用于任何类型的变量,甚至对象(假设标识符实际上引用了相同的实体,只是等效的对象不被视为相同)。

于 2020-08-15T15:59:30.773 回答
0

要获取唯一对象,您可以使用JSON.stringifyand JSON.parse

const arr = [{test: "a"}, {test: "a"}];
const unique = Array.from(new Set(arr.map(JSON.stringify))).map(JSON.parse);
console.log(unique);

于 2021-07-02T09:42:44.953 回答
-1

关于什么

    function unique(list) {
      for (i = 0; i<list.length; i++) {
        for (j=i+1; j<list.length; j++) {
          if (list[i] == list[j]) {
            list.splice(j, 1);
          }
        }
      }
    }
于 2014-09-11T18:07:25.890 回答