【问题标题】:How to get distinct elements(case insensitive) from array of objects using lodash如何使用 lodash 从对象数组中获取不同的元素(不区分大小写)
【发布时间】:2021-11-01 16:46:22
【问题描述】:

我有一个如下所示的数组,

[
  {
    "_id": "5e3ccb88c9b3027ef4977894",
    "name": "microsoft"
  },
  {
    "_id": "59ce020caa87df4da0ee2c77",
    "name": "Microsoft"
  },
  {
    "_id": "5e077c78bc0d663d7170ba1c",
    "name": "MICROSOFT"
  },
  {
    "_id": "608839e8d9271457814a7aa4",
    "name": "Microsoft "
  },
  {
    "_id": "5ecd46657ffa9b761a0e41cd",
    "name": "Microsoft  - MSN"
  },
  {
    "_id": "5dfb47adbc0d663d716fe25f",
    "name": "Microsoft  Alumni Foundation"
  }
]

现在我只需要一个 Microsoft,而不是使用 lodash 的这些案例组合。

预期输出,

[
  {
    "_id": "608839e8d9271457814a7aa4",
    "name": "Microsoft "
  },
  {
    "_id": "5ecd46657ffa9b761a0e41cd",
    "name": "Microsoft  - MSN"
  },
  {
    "_id": "5dfb47adbc0d663d716fe25f",
    "name": "Microsoft  Alumni Foundation"
  }
]

谁能帮我解决这个问题?找到了很多解决方案,但我需要不区分大小写的过滤器。

提前致谢。

【问题讨论】:

  • 您选择'Microsoft ...'是否有条件,还是只想选择您看到的第一个?
  • 不@lejlun,我只是不需要重复值,可能是小写或大写。我只想要唯一的名字。
  • 这是一个很好的方法,但没有找到任何方法来执行不区分大小写的过滤器。

标签: javascript node.js json lodash


【解决方案1】:

您可以使用 lodash 的 _.uniqBy(),它接受一个生成匹配条件的函数。在这种情况下,修剪字符串,并将其转换为小写:

const arr = [{"_id":"5e3ccb88c9b3027ef4977894","name":"microsoft"},{"_id":"59ce020caa87df4da0ee2c77","name":"Microsoft"},{"_id":"5e077c78bc0d663d7170ba1c","name":"MICROSOFT"},{"_id":"608839e8d9271457814a7aa4","name":"Microsoft "},{"_id":"5ecd46657ffa9b761a0e41cd","name":"Microsoft  - MSN"},{"_id":"5dfb47adbc0d663d716fe25f","name":"Microsoft  Alumni Foundation"}]

const result = _.uniqBy(arr, o => o.name.trim().toLowerCase())

console.log(result)
<script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.17.21/lodash.min.js" integrity="sha512-WFN04846sdKMIP5LKNphMaWzU7YpMyCU245etK3g/2ARYbPK9Ub18eG+ljU96qKRCWh+quCY7yefSmlkQw1ANQ==" crossorigin="anonymous" referrerpolicy="no-referrer"></script>

由于您想要一系列重复项中的最后一项,您可以反转数组,获取唯一项,然后将其反转回来:

const arr = [{"_id":"5e3ccb88c9b3027ef4977894","name":"microsoft"},{"_id":"59ce020caa87df4da0ee2c77","name":"Microsoft"},{"_id":"5e077c78bc0d663d7170ba1c","name":"MICROSOFT"},{"_id":"608839e8d9271457814a7aa4","name":"Microsoft "},{"_id":"5ecd46657ffa9b761a0e41cd","name":"Microsoft  - MSN"},{"_id":"5dfb47adbc0d663d716fe25f","name":"Microsoft  Alumni Foundation"}]

const result = _.reverse(_.uniqBy(
  _.reverse([...arr]), 
  o => o.name.trim().toLowerCase()
))

console.log(result)
<script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.17.21/lodash.min.js" integrity="sha512-WFN04846sdKMIP5LKNphMaWzU7YpMyCU245etK3g/2ARYbPK9Ub18eG+ljU96qKRCWh+quCY7yefSmlkQw1ANQ==" crossorigin="anonymous" referrerpolicy="no-referrer"></script>

【讨论】:

  • 似乎是 lodash 中最简洁的表达方式......但是uniqBy 似乎选择了第一个重复项,而 OP 的期望输出表明他们想要最后一个重复项。
  • 是的。错过了最后一个重复的部分。我也为此添加了一个解决方案,尽管现在它不那么简洁了。
【解决方案2】:

您可以使用_.filter_.toLower_.trim 来执行此操作。

我们可以保留seenSet() 的值,这样我们就知道我们以前见过哪些项目。在添加或检查此集合之前使用_.toLower_.trim,我们可以确保该项目不是数组中另一个项目的细微变化。

像这样:

let data = [ { _id: '5e3ccb88c9b3027ef4977894', name: 'microsoft' }, { _id: '59ce020caa87df4da0ee2c77', name: 'Microsoft' }, { _id: '5e077c78bc0d663d7170ba1c', name: 'MICROSOFT' }, { _id: '608839e8d9271457814a7aa4', name: 'Microsoft ' }, { _id: '5ecd46657ffa9b761a0e41cd', name: 'Microsoft  - MSN' }, { _id: '5dfb47adbc0d663d716fe25f', name: 'Microsoft  Alumni Foundation' }, ];

const testPrefixes = new Set();

let res = _.filter(data, (o) => {
  if (testPrefixes.has(_.trim(_.toLower(o.name)))) return false;
  else return testPrefixes.add(_.trim(_.toLower(o.name)));
});

console.log(res);
<script src="https://cdn.jsdelivr.net/npm/lodash@4.17.21/lodash.min.js"></script>

【讨论】:

  • 这一切都可以在没有lodash 的情况下完成,甚至可能更快。是否有需要lodash 的具体原因?
  • 谢谢@lejlun,这就是我想要的。非常感谢。
【解决方案3】:

这是一个无库的实用程序(在 TypeScript 中),我一直在做这件事:

const dedupeArrayBy = <T, TK>(items: T[], selector: (item: T) => TK): T[] => {
    const m = new Map(items.map((item) => [selector(item), item] as const));
    return [...m.values()];
};

所以你可以:

const deduped = dedupeArrayBy(items, v => v.name.trim().toLowerCase());

这里是 Javascript 翻译:

"use strict";
const dedupeArrayBy = (items, selector) => {
  const m = new Map(items.map((item) => [selector(item), item]));
  return [...m.values()];
};
let data = [{
  _id: '5e3ccb88c9b3027ef4977894',
  name: 'microsoft'
}, {
  _id: '59ce020caa87df4da0ee2c77',
  name: 'Microsoft'
}, {
  _id: '5e077c78bc0d663d7170ba1c',
  name: 'MICROSOFT'
}, {
  _id: '608839e8d9271457814a7aa4',
  name: 'Microsoft '
}, {
  _id: '5ecd46657ffa9b761a0e41cd',
  name: 'Microsoft  - MSN'
}, {
  _id: '5dfb47adbc0d663d716fe25f',
  name: 'Microsoft  Alumni Foundation'
}, ];
console.log(dedupeArrayBy(data, v => v.name.trim().toLowerCase()));

【讨论】:

    猜你喜欢
    • 2011-09-14
    • 1970-01-01
    • 2023-03-12
    • 2010-10-26
    • 2016-09-22
    • 2020-08-20
    • 2018-04-17
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多