【问题标题】:Create an array, based on the values of an existing array of objects in Javascript根据 Javascript 中现有对象数组的值创建一个数组
【发布时间】:2021-10-21 12:22:51
【问题描述】:

我有一个对象数组如下。

 const arr = [
    {
      categoryId: "I01",
      categoryName: "Category_one",
      price: 100
    },
    {
      categoryId: "I02",
      categoryName: "Category_two",
      price: 200
    },
    {
      categoryId: "I03",
      categoryName: "Category_three",
      price: 300
    },
    {
      categoryId: "I02",
      categoryName: "Category_two",
      price: 210
    },
    {
      categoryId: "I03",
      categoryName: "Category_three",
      price: 310
    }
 ]

我正在努力获得如下结果。这就像根据类别过滤整个数组。

arr2 = [
    {
      id: 0,
      categoryId: "I01",
      categoryName: "Category_one",
      minimum_price: 100,
      count: 1
    },
    {
      id: 1,
      categoryId: "I02",
      categoryName: "Category_two",
      minimum_price: 200,
      count: 2
    },
    {
      id: 2,
      categoryId: "I03",
      categoryName: "Category_three",
      minimum_price: 300,
      count: 2
    },
]

我已将结果创建到以下级别

const resArr = [];
    arr.forEach((item) => {
        let i = resArr.findIndex(x => x.categoryId == item.categoryId);
        if (i <= -1) {
            resArr.push({ categoryId: item.categoryId, categoryName: item.categoryName });
        }
    });
    resArr.forEach((o, i) => o.id = i);

得到了这个结果,

 res = [
        {
          id: 0,
          categoryId: "I01",
          categoryName: "Category_one"
        },
        {
          id: 1,
          categoryId: "I02",
          categoryName: "Category_two"
        },
        {
          id: 2,
          categoryId: "I03",
          categoryName: "Category_three"
        },
    ]

我需要有 minimum_price 值和 count 值。非常感谢您的建议。

【问题讨论】:

    标签: javascript arrays sorting reduce


    【解决方案1】:

    您可以将Array.prototype.reduceObject.values 一起使用:

    let id = -1;
    
    // Even though we're reducing to an object, Object.values will
    // extract the result to an array.
    const result = Object.values(arr.reduce(({
      categoryId,
      categoryName,
      price,
    }, acc) => {
      // If we don't already have something from that
      // category, make a new entry in the hash
      if (!(categoryId in acc)) acc[categoryId] = {
        categoryId,
        categoryName,
        minPrice: price,
        id: id++, // increment the id
        count: 0,
      };
    
      // Increase the count for that category by 1
      acc[categoryId].count += 1;
    
      // Set new minimum price if applicable
      if (acc[categoryId].price > price) acc[categoryId].price = price;
    
      // return the accumulator
      return acc;
    }, {}));
    

    【讨论】:

    • 嗨@Jared Smith,我检查了我的数据,但无法按照您的回答得到预期的结果。
    【解决方案2】:

    我建议这样做:

    首先,应用id 字段:

    arr.map(item=>({...item, id: Number(item.categoryId.slice(1))}))
    

    并将其转换为(有效)Map&lt;int, Category&gt;,您可以使用ArrayMap,但您应该知道这可能不是您想要的最终数组,因为它可能是稀疏的。

    (您可以将前一步与此合并):

    const map = [];
    for(const item of arr) {
      const id = Number(item.categoryId.slice(1))
      if(!map[id]) {
        map[id] = {
            id,
            categoryId: item.categoryId,
            categoryName: item.categoryName,
            minimum_price: item.price,
            count: 1
        }
      } else {
        map[id].count += 1
        map[id].minimum_price = Math.min(map[id].minimum_price, item.price)
      }
    }
    

    并使其成为您想要的最终数组。您可以只过滤掉空槽:

    return map.filter(Boolean)
    

    我强烈建议您将idcategoryId 保持一致。拥有某物可能会令人困惑。喜欢{id: 0, categoryId: 'I01'}

    这就是你会得到的(JSON 字符串化):

    [{"id":1,"categoryId":"I01","categoryName":"Category_one","minimum_price":100,"count":1},{"id":2,"categoryId":"I02","categoryName":"Category_two","minimum_price":200,"count":2},{"id":3,"categoryId":"I03","categoryName":"Category_three","minimum_price":300,"count":2}]
    

    当“categoryId”不包含任何整数时,您能否更新您的答案

    这取决于你是否还想要一个有意义的id 字段。 如果不是,则地图应该是Map&lt;string, Category&gt;(或对象):

    const map = {};
    for(const item of arr) {
      if(!map[item.categoryId]) {
        map[item.categoryId] = {
            categoryId: item.categoryId,
            categoryName: item.categoryName,
            minimum_price: item.price,
            count: 1
        }
      } else {
        map[item.categoryId].count += 1
        map[item.categoryId].minimum_price = Math.min(map[id].minimum_price, item.price)
      }
    }
    

    您需要将 map 转换为数组,这可以通过 Object.keysObject.valuesObject.entriesfor...in 循环来完成:

    Object.values(map)
    

    如果您仍然需要,请应用 id 字段:

    Object.values(map).map((v, id) => ({...v, id}))
    

    或者,如果您想要一个有意义的 id 字段,

    您必须找到一种方法以某种方式将 categoryId 映射为整数。

    【讨论】:

    • 你好,@Yongjian Wang,答案很支持,但是当“categoryId”不包含任何整数时,你能更新你的答案吗?
    猜你喜欢
    • 2021-12-25
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-02-28
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-01-08
    相关资源
    最近更新 更多