【问题标题】:Prevent pushing to array if duplicate values are present如果存在重复值,则防止推送到数组
【发布时间】:2021-01-19 11:45:56
【问题描述】:

我正在映射一个数组并基于数据我将Option 元素推入一个数组,如下所示

 let make_children: any | null | undefined = [];
  

  buyerActivityResult && buyerActivityResult.simulcastMyAccount.data.map((item: { make: {} | null | undefined; }, key: any) => {
    make_children.push(
      <Option key={key}>{item.make}</Option>
    );
  });

以下数据数组有几个对象,这些对象有一个名为model的属性。

buyerActivityResult.simulcastMyAccount.data

如果属性model 有重复数据,我想防止将选项插入我的数组。对于所有相似的模型值,它只需要推送一次。

我该怎么做?

我试过这样的

 buyerActivityResult && buyerActivityResult.simulcastMyAccount.data.map((item: { model: {} | null | undefined; }, key: any) => {
    model_children.indexOf(item.model) === -1 && model_children.push(
      <Option key={key}>{item.model}</Option>
    );
  });

但仍有重复的值被推入我的数组。

【问题讨论】:

  • 为什么要将数据推送到地图函数内的数组中?
  • model_children 是从哪里来的?
  • 尝试给一个Minimal Reproducible 代码块,你的代码是一团糟。另外,如果该数组很大,我建议将数据存储在像对象这样的哈希图中。

标签: javascript arrays reactjs typescript


【解决方案1】:

很难说出您想要达到的目标,但看起来 地图 可能不是适合这项工作的工具。

map 返回与您调用 map 的原始数组大小相同的长度数组。

如果我的假设是正确的,那么您的 buyerActivityResult.simulcastMyAccount.data 数组有重复值,您想根据 model 属性删除这些重复值吗?实现此目的的一种方法是为此使用 lodash 库,使用 uniq 函数:

const uniqueResults = _.uniq(buyerActivityResult.simulcastMyAccount.data, (item) => item.model);

【讨论】:

  • 对于提问的方式,我们可以猜到作者经验不足。所以我认为这个回复缺乏解释,但显然不值得投反对票,因为答案似乎是合法且最简单的方法。 (有些人会说它增加了依赖,但这不是这里的主题)。我对这个回复投了赞成票,以抵消难以理解的反对票。
【解决方案2】:

Array.prototype.map() 方法应该用于操作包含在执行操作的数组中的数据。要操作来自其他变量的数据,我建议使用 for-loop 块。

如果item.model是一个对象,函数Array.prototype.indexOf()总是返回-1,因为它比较对象的内存地址,而不是对所有属性值做深度比较。

从数组中删除重复数据的常用解决方案是将数组转换为Set,然后再转换回数组。不幸的是,这仅适用于主要类型值(字符串、数字、布尔值等),不适用于对象。

从这里开始,我将审查您的源代码并进行一些更改,并解释我为什么要应用这些更改。首先,假设make_children 数组稍后在您的代码中没有收到新的属性,我会将它变成一个常量。由于初始化的原因,我认为声明被改写了。

const make_children: any[] = [];

那么我认为你试图同时做太多事情。它使您的同事和您也难以阅读源代码(可能不是今天,但几周后会怎样……),并且几乎不可能进行测试、调试和改进。让我们至少分两个步骤来分解它。第一个是转换数据。例如删除重复项。第二个基于上一个操作的结果创建Option 元素。

const data: { make: any }[] = buyerActivityResult?.simulcastMyAccount?.data || [];
let options = data.map((item) => !!item.model); // removing items without model.
// Here the hard part, removing duplicates.
// - if the models inside your items have a property with unique value (like an ID) you can implement a function to do so yourself. Take a look at: https://stackoverflow.com/questions/2218999/remove-duplicates-from-an-array-of-objects-in-javascript
// - or you can use Lodash library like suggested Rezaa91 in its answer
options = _.uniq(data, (item) => item.model);

现在您只需创建Option 元素。

for (var i = 0; i < options.length; i++) {
    model_children.push(<Option key={i}>{options[i].model}</Option>);
}

// OR using the Array.prototype.map method (in this case, do not declare `model_children` at the beginning)

const model_children:[] = options.map((opt:any, i:number) => <Option key={i}>{opt.model}</Option>);

尽管您提供的代码执行缺乏上下文,但我希望我的回答能帮助您找到解决方案并鼓励您编写更清晰的源代码(为了您的同事和您未来的自己)。

PS:我对 ReactJs 一无所知。请原谅我的语法错误。

猜你喜欢
  • 2014-12-07
  • 2018-08-09
  • 1970-01-01
  • 2018-05-30
  • 2013-12-23
  • 1970-01-01
  • 2019-09-15
  • 2021-09-27
  • 1970-01-01
相关资源
最近更新 更多