所以我有一个值数组,如下所示

const foodsList = [
  {
    foodOrigin: "Padang",
    foodName: "Nasi Padang",
    originCode: "PDN"
  },
  {
    foodOrigin: "Padang",
    foodName: "Gulai",
    originCode: "PDN"
  },
  {
    foodOrigin: "Padang",
    foodName: "Rendang",
    originCode: "PDN"
  },
  {
    foodOrigin: "Palembang",
    foodName: "Pempek",
    originCode: "PLG"
  },
  {
    foodOrigin: "Palembang",
    foodName: "Tekwan",
    originCode: "PLG"
  },
  {
    foodOrigin: "Yogyakarta",
    foodName: "Gudeg",
    originCode: "YKT"
  }
];

我想对数组进行过滤,因此结果将如下所示

const filteredFoodsList = [
  {
    foodOrigin: "Padang",
    originCode: "PDN"
  },
  {
    foodOrigin: "Palembang",
    originCode: "PLG"
  },
  {
    foodOrigin: "Yogyakarta",
    originCode: "YKT"
  }
];

为了达到这个结果,我try 了如下所示,但是有没有更干净、更好的方法呢?(尤其是因为我的实际数组中包含500多个数据)

const filteredFoodsList = [];
for (let i = 0; i < foodsList.length; i++) {
  if (i === 0) {
    filteredFoodsList.push({
      originCode: foodsList[i].originCode,
      foodOrigin: foodsList[i].foodOrigin
    });
  }
  let isExist = false;
  for (let j = 0; j < filteredFoodsList.length; j++) {
    if (foodsList[i].originCode === filteredFoodsList[j].originCode) {
      isExist = true;
    }
  }
  if (!isExist) {
    filteredFoodsList.push({
      originCode: foodsList[i].originCode,
      foodOrigin: foodsList[i].foodOrigin
    });
  }
}

推荐答案

正如操作员所说,应该把重点放在性能上,所以..

The Map could be the fastest way to collect unique values.
(I've borrowed Array.from(map, ([originCode, foodOrigin]) => ({ foodOrigin, originCode })) from Nina's answer, really elegant).

但这不会影响性能,因为生成的数组应该很小.

但她忘了加上Map::has()美元的支票,这真的能显著提高性能.

重要的是迭代源数组的速度有多快.一如既往,我认为不可能有比for(let i = 0; ...)更快的事情了.

const foodsList=[{foodOrigin:"Padang",foodName:"Gulai",originCode:"PDN"},{foodOrigin:"Padang",foodName:"Rendang",originCode:"PDN"},{foodOrigin:"Palembang",foodName:"Pempek",originCode:"PLG"},{foodOrigin:"Palembang",foodName:"Tekwan",originCode:"PLG"},{foodOrigin:"Yogyakarta",foodName:"Gudeg",originCode:"YKT"}];

const map = new Map;
for (let i = 0; i < foodsList.length; i++) {
    const item = foodsList[i];
    map.has(item.originCode) || map.set(item.originCode, item.foodOrigin);
}

const result = Array.from(map, ([originCode, foodOrigin]) => ({ foodOrigin, originCode }));

console.log(result);

和一个基准:

![enter image description here

<script benchmark data-count="1">

    const chunk = [{ foodOrigin: "Padang", foodName: "Gulai", originCode: "PDN" }, { foodOrigin: "Padang", foodName: "Rendang", originCode: "PDN" }, { foodOrigin: "Palembang", foodName: "Pempek", originCode: "PLG" }, { foodOrigin: "Palembang", foodName: "Tekwan", originCode: "PLG" }, { foodOrigin: "Yogyakarta", foodName: "Gudeg", originCode: "YKT" }];
    var foodsList = [];
    let count = 10000000;
    while (count--) {
        foodsList.push(...chunk);
    }
    
    // @benchmark Peter's solution

    foodsList
      .reduce((collector, { foodOrigin, originCode = null }) => {

        if (originCode !== null && !collector.lookup.has(foodOrigin)) {

          collector.lookup.set(foodOrigin, true);
          collector.result.push({
            foodOrigin,
            originCode,
          });
        }
        return collector;

      }, { lookup: new Map, result: [] }).result;

    // @benchmark Nina's solution
    Array.from(
        foodsList.reduce((m, { foodOrigin, originCode }) => m.set(foodOrigin, originCode), new Map),
        ([foodOrigin, originCode]) => ({ foodOrigin, originCode })
    );

    // @benchmark Alexander's solution
    const map = new Map;
    for (let i = 0; i < foodsList.length; i++) {
        const item = foodsList[i];
        map.has(item.originCode) || map.set(item.originCode, item.foodOrigin);
    }

    Array.from(map, ([originCode, foodOrigin]) => ({ foodOrigin, originCode }));

    // @benchmark Nina's improved

    Array.from(
        foodsList.reduce((m, { foodOrigin, originCode }) => {
            m.has(foodOrigin) || m.set(foodOrigin, originCode);
            return m;
        }, new Map),
        ([foodOrigin, originCode]) => ({ foodOrigin, originCode })
    );


</script>
<script src="https://cdn.jsdelivr.net/gh/silentmantra/benchmark/loader.js"></script>

Javascript相关问答推荐

reaction如何在不使用符号的情况下允许多行返回?

添加/删除时React图像上传重新渲染上传的图像

如何使用React渲染器放置根dis?

当promise 在拒绝处理程序被锁定之前被拒绝时,为什么我们会得到未捕获的错误?

Redux查询多个数据库Api reducerPath&

在这种情况下,如何 for each 元素添加id?

为什么当我解析一个promise时,输出处于挂起状态?

setcallback是什么时候放到macrotask队列上的?

变量的值在Reaction组件中的Try-Catch语句之外丢失

我可以使用使用node.js创建的本地主机来存储我网站上提交的所有数据吗?没有SQL或任何数据库.只有HTML语言

正则表达式,允许我匹配除已定义的子字符串之外的所有内容

在浏览器中触发插入事件时检索编码值的能力

Rxjs流中生成IMMER不能在对象上操作

钛中的onClick事件需要在两次点击之间等待几秒钟

TinyMCE 6导致Data:Image对象通过提供的脚本过度上载

处理app.param()中的多个参数

用另一个带有类名的div包装元素

如何使用[ModelJSON,ArrayBuffer]调用tf.loadGraphModelSync

暂停后只有一次旋转JS

如果我将高度设置为其内容的100%,则在Java脚本中拖动以调整面板大小时会冻结