如何在 JavaScript 中创建唯一项目列表? [复制]
Posted
技术标签:
【中文标题】如何在 JavaScript 中创建唯一项目列表? [复制]【英文标题】:How to create a list of unique items in JavaScript? [duplicate] 【发布时间】: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
可能重复[获取数组中的所有唯一值(删除重复)***.com/questions/1960473/…
【参考方案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<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.stringify
和JSON.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) 解决方案适用于小型数组,但一旦数组变大我就不会使用它。以上是关于如何在 JavaScript 中创建唯一项目列表? [复制]的主要内容,如果未能解决你的问题,请参考以下文章
如何在 HTML/Javascript 中创建可编辑的组合框?
如何在 javascript 中创建一个单词的所有可能字谜的列表?