如何最好地从数组中删除重复的字符串

5
我们已经成功创建了下面的脚本,用于从数组中删除任何重复的字符串。然而,为了让Angular在ng-repeat循环时保持数组的顺序,保留数组元素的原始索引非常重要。此外,我们希望剩余的元素保持相同的索引位置。请参考下方代码:
scope.feedback = _.map(_.pluck(item.possibleAnswers, 'feedback'), function (element, index, collection) {
    return collection.slice(0, index).indexOf(element) === -1 ? element : '';
});

以上代码可以运行,但我们认为必须有比这更简单的解决方案。是否有人遇到过类似问题并想出了更好的解决方案?


使用reduce来实现同样的目的如何?这里是一个fiddle,使用数字而不是字符串,但我认为这并不重要 https://jsfiddle.net/58z7nrfy/ - llamerr
你是在处理字符串数组还是任意类型的数组?你能提供一些使用案例或者类似于之前和之后的示例吗? - Morteza Tourani
7个回答

6
如果目标浏览器支持 展开运算符,那么请在控制台中尝试以下代码:
[...new Set(['3','1','1','5'])]
// ['3','1','5']

如果浏览器支持 Array.from,你也可以这样写:

Array.from(new Set(['3','1','1','5']))
// ['3','1','5']

所以这样做是可以的,但我需要保持数组的长度不变。 - Max Lynn
1
@MaxLynn 如果你从中删除了值,如何保持相同的长度? - llamerr
各位需要更深入地阅读问题。我们需要保持数组的顺序,以便知道哪些不需要任何文本。这就是为什么在脚本中我们用空字符串替换重复项的原因。 - Max Lynn
@MaxLynn 只需添加 else p.push('') - 我更新了我的示例。就这样吗? - llamerr
我现在从你的代码中看到了,但是在文本中你从来没有提到过需要用空字符串替换这些字符串 - bjaksic
@MaxLynn,但我怀疑任何代码都不会比你已经拥有的更短或更简单。实际上,即使将我的代码压缩成一个字符串,它可能已经更长了... - llamerr

5

使用reduce方法的变量 https://jsfiddle.net/58z7nrfy/1/

var a = [1,2,3,1,2,3,2,2,3,4,5,5,12,1,23,4,1];

var b = a.reduce(function(p,c,i,a){
  if (p.indexOf(c) == -1) p.push(c);
  else p.push('')
  return p;
}, [])
console.log(b)

[1, 2, 3, "", "", "", "", "", "", 4, 5, "", 12, "", 23, "", ""]

这是一个包含数字和空字符串的列表。

你的方法稍微快一些,所以感谢你的回答。 - Max Lynn

4
除了提到的答案外,您还可以使用Lodash union函数来实现:
let duplicates = ['Hello', 'Hi', 'Hello'];
let uniques = _.union(duplicates);

唯一值将是:["Hello", "Hi"]


2
您可以使用一个类型明确的Map,它可以防止使用Array#indexOf进行重复迭代。请注意保留HTML标签。

var a = [1, 2, 3, 1, 2, 3, 2, 2, 3, 4, 5, 5, 12, 1, 23, 4, 1, '23'],
    filtered = a.filter(function (a) {
        if (!this.has(a)) {
            this.set(a, true);
            return true;
        }
    }, new Map);

console.log(filtered);


您的答案将数字和字符串数字视为不同的项,这是您想要的吗?顺便说一句,我完全没有理解 OP 的请求。 - Morteza Tourani
@mortezaT,也许我也不知道 :) - Nina Scholz

1

被接受的答案非常低效。可以使用reduce和哈希表或映射对象来提高性能。在这里,我更喜欢在reduce的位置上使用map。然而,我猜通过将地图加倍扩展@Nina Scholz的方法,OP问题的正确答案如下;

var   a = [1, 2, 3, 1, 2, 3, 2, 2, 3, 4, 5, 5, 12, 1, 23, 4, 1, '23'],
unified = a.map(function(e) {
                  return this.has(e) ? void 0 : (this.set(e,"Cheap Thrills"),e);
                }, new Map());
console.log(unified);

如果这是一个长度任意的生产代码,那么我会使用标准函数来实现map方法,而不是使用functor,因为在大型数组中,它能够带来额外的性能提升(例如大小为10K+)。

1
我认为lodash的uniq()非常有用。
let data = [1,2,3,1,2,3,2,2,3,4,5,5,12,1,23,4,1];
let uniqData = _.uniq(data ,(e) => {
 return e;
});

然后输出将是:
[1, 2, 3, 4, 5, 12, 23]

0
我使用了这个脚本:
var words = ['one', 'one', 'two', 'three', 'three', 'two'];
    var result = [];
    for(i=0;i<words.length;i++){
      if(result.indexOf(words[i]) == -1){
        result.push(words[i])
      }
    }

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接