【问题标题】:javascript Filter array with duplicate elements at a specific occurrencejavascript过滤器数组在特定出现处具有重复元素
【发布时间】:2019-07-24 06:44:06
【问题描述】:

我有一个名称数组,它们都有重复。

let arr = ['John', 'Jack', 'John', 'Jack', 'Jack', 'June', 'June'];

我想用一些重复元素创建一个新数组,指定它们出现的实例。

例如,我可能希望数组只包含第二次出现的 John、Jack 和 June。数组将如下所示:

'John', 'Jack', 'June'

为了实现这一点,我声明了一个对象ni 并循环通过arr 为每个名称对应的对象添加属性;该属性将保存一个数组的值,该数组包含名称出现的每个索引。

let ni  = {};

for(let i = 0; i < arr.length; i++) {
  let name = arr[i];
  if(nc.hasOwnProperty(name)) {
    ni[name].push(i);
  } else {
    ni[name] = [i];
  }
}

console.log(ni);
// > Object { John: Array [0, 2], Jack: Array [1, 3, 4], June: Array [5, 6] }

在我的 Array.filter 函数中,我检查元素的索引是否等于对应于相同名称的对象属性的索引 1。

let newArr = arr.filter(function(name) {
  if(ni.hasOwnProperty(name)) {
    return arr.indexOf(name) === ni[name][1];
  }
});

这应该将Johnindex 2Jackindex 3Juneindex 6 返回到新数组。

但是,这没有奏效。将newArr 记录到控制台将输出一个与原始数组完全一致的数组。

> Array ["John", "Jack", "John", "Jack", "Jack", "June", "June"]

【问题讨论】:

标签: javascript arrays string function object


【解决方案1】:

你可以像这样使用一些简单的数组逻辑:

let newArr = arr.filter((e, i) => i == ni[e][1]);

【讨论】:

  • @trincot 如果数组不包含足够的元素 - 所以如果它未定义,它将取而代之的是数组的最后一个元素。
  • 但是对于非空字符串来说,这总是真实的(注意== 优先于||)。其次,它违背了目的,因为length 可能是 1,然后你会得到第一次出现。 OP想要第二个......
  • 所以我应该删除|| 部分?
  • 是的,我打算和你同时回答,但只是有区别,所以没有它更好。
  • 好的,感谢@trincot 的反馈,我仍在完善我对优先级的了解,我会记住你提到的内容。
【解决方案2】:

您可以使用reduce 来计算每个名称的出现次数。如果名称的计数为 2,则推送到另一个数组。这样您就不必运行嵌套数组方法:

const array = ['Jane', 'John', 'Jack', 'John', 'Jack', 'Jack', 'June', 'June'];
const filtered = [];
const count = array.reduce((a, name) => {
  a[name] = a[name] + 1 || 1;
  if(a[name] === 2)
    filtered.push(name)
  
  return a;
}, {});

console.log(filtered)

或者获取count > 1的计数器的键

const array = ['Jane', 'John', 'Jack', 'John', 'Jack', 'Jack', 'June', 'June'],
      count = array.reduce((a, n) => (a[n] = a[n] + 1 || 1, a), {}),
      filtered = Object.keys(count).filter(n => count[n] > 1);
      
console.log(filtered)

【讨论】:

    【解决方案3】:

    我正在创建一个对象而不是一个数组,因为它似乎更适合从名称映射到第二次出现的索引。它的工作原理是这样的:indexOf 返回数组中第一次出现的元素的索引,所以如果indexOf 不等于当前索引,那么它是第二次或更晚出现,然后我检查名称是否已经在返回对象,所以我知道它不是第 3 次或更晚出现。

    let arr = ['John', 'Jack', 'John', 'Jack', 'Jack', 'June', 'June'];
    let newObj = arr.reduce(function(acc, cur, idx) {
      if (arr.indexOf(cur)!==idx && !acc[cur]) { acc[cur] = idx; }
    	return acc;
    }, {});
    console.log(newObj);

    【讨论】:

      猜你喜欢
      • 2011-06-29
      • 1970-01-01
      • 2021-04-24
      • 2019-01-18
      • 2017-07-19
      • 1970-01-01
      • 1970-01-01
      • 2019-11-23
      • 2017-04-13
      相关资源
      最近更新 更多