【问题标题】:return a filtered array of objects返回过滤后的对象数组
【发布时间】:2017-10-07 05:13:07
【问题描述】:

我正在努力从一组对象中删除欺骗。我有一个数组,storedItems:

var storedItems = [
    {text: "1", checked: false },
    {text: "2", checked: false },
    {text: "3", checked: false },
    {text: "string", checked: false }
]

等等。文本值是字符串或数字字符串。我可以在散列或 uniqueVals 中识别唯一文本值...

filterDupes(storedItems);

function filterDupes(input) {
    var hash = {};
    var uniqueVals = [];
    input.forEach(obj => {
        hash[obj.text] = true;
    })
    var uniqueVals = Object.keys(hash); // Array
    return input.filter(function(obj, ix, arr) {
        uniqueVals.indexOf(obj.text) !== -1; // NOPE
    }) // .filter
} // filterDupes

...这是如何将哈希键或 uniqueVals 与输入数组对象进行比较,即,我到底需要什么(没有 for 循环或另一个 forEach?)来返回过滤后的数组,这让我大吃一惊我的头靠在墙上,试图找到一些版本的 return hash[obj.text] == obj.text;或返回 (hash.key === obj.text)

编辑:在这里小提琴:https://jsfiddle.net/WTFoxtrot/by3nhy4n/2/

【问题讨论】:

  • 你可能想使用 Set object developer.mozilla.org/en/docs/Web/JavaScript/Reference/… 而不是运行 forEach 循环然后 Object.keys 方法。
  • 你展示的代码现在做了什么?它不工作吗?如果它不起作用,它是通过什么方式不起作用的?
  • @Yanaro 回复:设置对象,是的,我刚刚知道,谢谢。
  • @torazaburo 我展示的代码返回一个空数组。
  • 你必须从你的过滤函数中返回一些东西。

标签: javascript arrays filter duplicates


【解决方案1】:

使用Array.prototype.map()Array.prototype.filter() 的组合:

let items = [
    {text: "1", checked: false},
    {text: "2", checked: false},
    {text: "3", checked: false},
    {text: "string", checked: false},
    {text: "2", checked: false},
    {text: "string", checked: false},
    {text: "1", checked: false}
];
let values = items.map(it => it.text).filter((v, i, a) => a.indexOf(v) === i);

console.log(values); // ["1", "2", "3", "string"]

过滤器闭包(v, i, a) => a.indexOf(v) === i 过滤掉除该值第一次出现之外的任何位置出现的所有值。

使用相同的原则,如果你想过滤对象数组本身而不是返回唯一值列表,你可以使用Array.prototype.filter()Array.prototype.find()

let items = [
    {text: "1", checked: false},
    {text: "2", checked: false},
    {text: "3", checked: false},
    {text: "string", checked: false},
    {text: "2", checked: false},
    {text: "string", checked: false},
    {text: "1", checked: false}
];
let filtered = items.filter((x, i, a) => a.find(y => x.text === y.text) === x);

console.log(filtered); // [{"text": "1", "checked": false}, {"text": "2", "checked": false}, {"text": "3", "checked": false}, {"text": "string", "checked": false}]

【讨论】:

  • 谢谢!您的 v2 是我所需要的:我想返回过滤后的对象数组,而不仅仅是我拥有的 uniqueVals,使用哈希。我对几件事感到好奇;以为我在别处读到使用散列或 Set() 比 indexof 更有效,尽管我无法想象你的 v1 值声明如何如此漂亮。此外,当我阅读 .find() 时,如果您有时间,我将非常感谢您对 .find 语句的解释 - 这有点让人费解。干杯,W
【解决方案2】:

V2:使用 Set 对象,你可以使用数组 indexOf 相同的方式:

function filterDupes(input) {
  var unique = new Set();

  return input.filter((obj, ix, arr) => {
    if(!unique.has(obj.text)) {
       unique.add(obj.text);
       return true;
    }
    return false;
  })
}

如果你不想过多改变你的功能:

...
return input.filter((obj, ix, arr) => {
    var index = uniqueVals.indexOf(obj.text);
    if(index !== -1) {
    // Remove the element from unique array
       uniqueVals.splice(index,1);
       return true;
    }
    return false;
})

V1:不正确。 以前,您的功能有点不正确。它实际上什么也没做。您只需将文本推送到一个数组,然后再次检查该文本是否存在于该数组中。

var storedItems = [
  {text: "1", checked: false },
  {text: "2", checked: false },
  {text: "3", checked: false },
  {text: "string", checked: false }
];

function filterDupes(input) {
  //Your previous code inside function
  ...
  return input.filter(function(obj, ix, arr) {
     return uniqueVals.indexOf(obj.text) !== -1;
  })
}

【讨论】:

  • 谢谢。对象中的分号是拼写错误,我已经编辑了我的帖子,将它们删除。我认为我的小提琴(我帖子中的 url)是您的建议,但我仍然没有返回任何内容(实际上在 jsfiddle 中我什么也没有得到,而在 repl 中我返回一个空对象)。我错过了什么?
  • 非常感谢您详细说明这一点。为了理解,我已经尝试了这两种方法。我非常感谢您提供基于我所拥有的解决方案;我个人觉得这最有帮助,也许是因为固执,但尽管如此。也就是说,一旦我摸到了你的 V1,我就会更喜欢它,因为它清晰且明显更简洁。我实际上更喜欢它而不是我接受的答案,因为它对学习者更友好(但改变接受的答案可能是不好的 SO 形式?)。我希望得到更多关于 OP 来自哪里的尊重的答案。干杯!
猜你喜欢
  • 2021-10-02
  • 1970-01-01
  • 2019-01-22
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-12-13
  • 2021-12-12
相关资源
最近更新 更多