【问题标题】:How to create a list of unique items in JavaScript? [duplicate]如何在 JavaScript 中创建唯一项目列表? [复制]
【发布时间】:2012-07-26 04:25:37
【问题描述】:

在我的 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);
}

【问题讨论】:

  • 根据你定义的优雅,你可以在github上查找下划线的唯一来源
  • 下划线仅用于字符串更昂贵,并且由于需要在一般情况下工作而不太优雅
  • 你需要reduce函数吗?如果您只需要唯一值,您可以在请求视图时使用group=true 选项。有关这方面的更多信息,请参阅CouchDB Wiki
  • 可能重复[获取数组中的所有唯一值(删除重复)stackoverflow.com/questions/1960473/…

标签: javascript arrays couchdb


【解决方案1】:

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

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

*在 Safari 中测试

【讨论】:

  • 你也可以只做new Set([1,2,4,6]),这不那么难看
  • new Set(list) 只会创建一个 Set。
  • 是的,你是对的,我的意思是Array.from(new Set([1,2,4,6])),看看我的回答
【解决方案2】:

2021 年答案:

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

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

Updated fiddle

旧答案仅作记录:

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

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;
}

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

我创建了一个example,用于测试您和我的解决方案。试着玩一下。

【讨论】:

  • 在处理集合和循环时,算法的速度总是很重要的。
  • 如果我使用for(var i=0; i&lt;arr.length; ++i),它会在每个循环中重新计算数组的长度吗?或者为什么要创建一个单独的l 变量?
  • @MarkusMeskanen 这取决于特定的 JavaScript 引擎实现。另外,不要忘记属性查找时间。
  • 今天通过 chrome 打开测试链接显示测试速度几乎没有差异。这个答案是最新的还是浏览器优化了性能差异?我已经更新了 jsfiddle 以及我的 indexOf 命题。
  • @FélixAdriyelGagnon-Grenier 奇怪。我仍然在 Linux Chrome 中获得了大约 0.7-0.8 的比率。但有时它> 1。所以看起来 ES 引擎现在以不同的方式工作。
【解决方案3】:

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

    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 的键相等概念所困扰。

【讨论】:

  • 漂亮,能够在 ember.js 中使用它来使用 Arrayproxy 的“过滤器”功能过滤记录数组
【解决方案4】:

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

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));
};

:)

【讨论】:

    【解决方案5】:

    如果你输入整数参数,使用 Object.keys 会给你字符串 (uniq([1,2,3]) => ['1','2','3']。这里是 Array.reduce :

    function uniq(list) {
        return list.reduce((acc, d) => acc.includes(d) ? acc : acc.concat(d), []);
    }
    

    【讨论】:

      【解决方案6】:

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

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

      您也可以通过添加以下内容来忽略 undefined 值(通常很方便):

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

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

      【讨论】:

      • 或许可以使用new Set 来获得更多乐趣
      【解决方案7】:

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

      我们可以使用Array的indexOf方法在push之前验证其中是否存在item:

      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);

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

      【讨论】:

        【解决方案8】:

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

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

        【讨论】:

          【解决方案9】:

          怎么样

              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);
                    }
                  }
                }
              }
          

          【讨论】:

          • 运行list.splice()后需要将j递减。这种 O(N^2) 解决方案适用于小型数组,但一旦数组变大我就不会使用它。
          猜你喜欢
          • 1970-01-01
          • 2011-10-19
          • 2016-05-09
          • 2021-10-20
          • 1970-01-01
          • 1970-01-01
          • 2010-11-26
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多