【问题标题】:Remove duplicates from an array of objects based on the first 3 words of object property根据对象属性的前 3 个单词从对象数组中删除重复项
【发布时间】:2021-03-15 15:34:40
【问题描述】:

我有这个有很多重复条目的对象数组。我可以清理数组并删除重复的数组,但问题是我需要删除那些根据属性的前 3 个单词匹配的数组。

假设这是数组:

let arr = [
     {
         text: "Be good and you will be lonely. But there’s nothing wrong with being lonely.",
         id: 1
     },
     {
         text: "Coffee is a way of stealing time.",
         id: 2
     },
     {
         text: "Be good and you will be lonely. But there’s nothing wrong with being lonely.",
         id: 3
     }
];

我想匹配每个文本的前 3 个单词,如果匹配,则从旧数组中删除一个匹配的对象并将删除的对象推送到新数组。

到目前为止,我可以使用这段代码删除重复的代码,但我不知道下一步该怎么做。

let texts     = {};

arr = arr.filter(function(currentObject) {
      if (currentObject.text in seenNames) {
           return false;
      } else {
           seenNames[currentObject.text] = true;
           return true;
      }
});

如果有人指出我正确的方向,那将是一个很大的帮助。

更新:

我用与以前不同的方法重新开始了整个事情。正如@Andreas 和@freedomn-m 所说,我根据前三个单词拆分项目,然后尝试通过匹配拆分项目来过滤原始数组。但现在我无需任何过滤就可以取回所有值。

let arr = [{
    "text": "Be good and you will be lonely. But there’s nothing wrong with being lonely.",
    "id": 1
  },
  {
    "text": "Coffee is a way of stealing time.",
    "id": 2
  },
  {
    "text": "Be good and you will be lonely. But there’s nothing wrong with being lonely.",
    "id": 3
  }
];

let removedItems = [];


let filtered = arr.filter((item, index) => {
  let splitItem = item["text"].split(" ").slice(0, 3).join(" ").toLowerCase();

  if (item["text"].toLowerCase().startsWith(splitItem, index + 1)) {
    return item;
  } else {
    removedItems.push(item);
  }

});



console.log(filtered);
console.log(removedItems);

【问题讨论】:

  • 所以想办法得到“前三个字”。您是否可以使用明显的分隔符(例如在该分隔符处拆分字符串)...到目前为止,您尝试过什么来自己解决这个问题?
  • @Andreas 不,没有明显的分隔符。它们只是简单的文本片段。不,我只能删除重复的。就像完全匹配的重复一样。
  • “Coffee”是一个词,“is”是一个词,......没有“Coffeeis”,所以必须将它们分开......
  • 数据是动态的。这完全取决于用户文本将是什么。可以用前三个空格分开吗?
  • 现在你明白了......

标签: javascript jquery arrays


【解决方案1】:

对于如何获得 3 个单词的原始问题,一种选择是使用 .split() .slice() 和 .join():

var firstWords = item["text"].split(" ").slice(0, 3).join(" ");

然后,您可以直接用 firstWords 替换 currentObject.text,来自原始问题:

let texts = {};
arr = arr.filter(function(currentObject) {
    if (firstWords in seenNames) {
         return false;
    } else {
         seenNames[firstWords] = true;
         return true;
    }
});

更新尝试这样做,但有 2 个问题:

  • .filter(function(item)) 必须返回 true/false(就像它最初所做的那样)而不是 item/nothing。

  • item["text"].toLowerCase().startsWith(splitItem) 将始终为真,因为 splitItem 是从 item["text"] 构建的

removedItems 附加列表添加到原始列表中:

let arr = [{
    "text": "Be good and you will be lonely. But there’s nothing wrong with being lonely.",
    "id": 1
  },
  {
    "text": "Coffee is a way of stealing time.",
    "id": 2
  },
  {
    "text": "Be good and you will be lonely. But there’s nothing wrong with being lonely.",
    "id": 3
  }
];

let removedItems = [];
let seenNames = {};

let filtered = arr.filter((item, index) => {
  let splitItem = item["text"].split(" ").slice(0, 3).join(" ").toLowerCase();
  
  if (splitItem in seenNames) {
    // already exists, so don't include in filtered, but do add to removed
    removedItems.push(item);
    return false;
  }
   
  // doesn't exist, so add to seen list and include in filtered
  seenNames[splitItem] = true;
  return true;
});

console.log(filtered);
console.log(removedItems);

【讨论】:

    猜你喜欢
    • 2012-05-17
    • 1970-01-01
    • 2020-06-29
    • 1970-01-01
    • 1970-01-01
    • 2016-11-08
    • 1970-01-01
    • 2020-04-28
    • 2021-07-09
    相关资源
    最近更新 更多