对一个对象数组中的两个值求和,然后插入另一个对象数组

时间:2018-10-11 22:20:24

标签: javascript arrays object mapping

我有一个称为存储的对象数组:

stores = [
  {
    storeId: 1,
    city: "San Francisco",
    state: "CA",
  },
  {
    storeId: 2,
    city: "Seattle",
    state: "WA",
  },
  {
    storeId: 3,
    city: "Vancouver",
    state: "BC",
  },
  {
    storeId: 4,
    city: "Los Angeles",
    state: "CA",
  },
]

和另一个称为item的对象数组:

items = [
  {
    itemId: 1,
    cost: 10,
    price: 20,
    sold: false,
    _storeId: 1,
  },
  {
    itemId: 2,
    cost: 10,
    price: 20,
    sold: false,
    _storeId: 1,
  },
  {
    itemId: 3,
    cost: 5,
    price: 12,
    sold: true,
    _storeId: 2,
  },
  {
    itemId: 4,
    cost: 12,
    price: 20,
    sold: false,
    _storeId: 3,
  },
  {
    itemId: 5,
    cost: 2,
    price: 10,
    sold: false,
    _storeId: 4,
  },
  {
    itemId: 6,
    cost: 10,
    price: 50,
    sold: true,
    _storeId: 4,
  },
]

我想按商店汇总以下类别:

  • 总费用
  • 总价格

然后按商店计数总项目数:

  • TotalItems

然后计算商店出售的小计商品:

  • SoldItems

所以我的最终存储阵列看起来像这样:

storesUpdated = [
  {
    storeId: 1,
    city: "San Francisco",
    state: "CA",
    totalCost: 20,
    totalPrice: 40,
    countTotalItems: 2,
    countSoldItems: 0
  },
  {
    storeId: 2,
    city: "Seattle",
    state: "WA",
    totalCost: 5,
    totalPrice: 12,
    countTotalItems: 1,
    countSoldItems: 1
  },
  {
    storeId: 3,
    city: "Vancouver",
    state: "BC",
    totalCost: 12,
    totalPrice: 20,
    countTotalItems: 1,
    countSoldItems: 0
  },
  {
    storeId: 4,
    city: "Los Angeles",
    state: "CA",
    totalCost: 12,
    totalPrice: 60,
    countTotalItems: 2,
    countSoldItems: 1
  },
]

我尝试过映射到商店数组,但是卡在这里:

const storesUpdated = stores.map((store) => {
   = {}
  items.forEach(item => {
    if (item._storeId === store.storeId) {
      return totalCost {
        'storeId' : item.storeId,

      }
    }
  })
})

有什么想法吗?非常感谢。

2 个答案:

答案 0 :(得分:1)

const stores = [{storeId:1,city:"San Francisco",state:"CA",},{storeId:2,city:"Seattle",state:"WA",},{storeId:3,city:"Vancouver",state:"BC",},{storeId:4,city:"Los Angeles",state:"CA",},]
const items = [{itemId:1,cost:10,price:20,sold:!1,_storeId:1,},{itemId:2,cost:10,price:20,sold:!1,_storeId:1,},{itemId:3,cost:5,price:12,sold:!0,_storeId:2,},{itemId:4,cost:12,price:20,sold:!1,_storeId:3,},{itemId:5,cost:2,price:10,sold:!1,_storeId:4,},{itemId:6,cost:10,price:50,sold:!0,_storeId:4,},]

const storesUpdated = stores.map((store) => {
  const updatedStore = { ...store,
    totalCost: 0,
    totalPrice: 0,
    countTotalItems: 0,
    countSoldItems: 0
  }
  
  items.forEach(item => {
    if (item._storeId === store.storeId) {
      updatedStore.totalCost += item.cost
      updatedStore.totalPrice += item.price
      updatedStore.countTotalItems += 1
      updatedStore.countSoldItems += item.sold ? 1 : 0
    }
  })
  
  return updatedStore
})

console.log(storesUpdated)

答案 1 :(得分:0)

如果只想循环遍历数据,则可以分两步执行合并:

  • 创建“空”存储并通过id在单个reduce中对其进行索引:(在stores上循环一次)

    const Store = (data) => ({ /* ... */ });
    const storesById = storeData => storeData.reduce(
      (map, sd) => Object.assign(map, { [sd.storeId]: Store(sd) }),
      {}
    );
    
  • 遍历项目并将其合并到相应的商店中:(items上的一个循环)

    const addItemToStoreMap = (storeMap, item) => ({
      ...storeMap,
      [item._storeId]: addItemToStore(storeMap[item._storeId], item)
    });
    

请注意,使用对象散布语法创建所有新对象会抵消性能的提高,但这仍然是O(n + m)而不是O(n * m)还是很不错的。

将它们放在一起:

const storeData = [{storeId:1,city:"San Francisco",state:"CA",},{storeId:2,city:"Seattle",state:"WA",},{storeId:3,city:"Vancouver",state:"BC",},{storeId:4,city:"Los Angeles",state:"CA",},]
const itemData = [{itemId:1,cost:10,price:20,sold:!1,_storeId:1,},{itemId:2,cost:10,price:20,sold:!1,_storeId:1,},{itemId:3,cost:5,price:12,sold:!0,_storeId:2,},{itemId:4,cost:12,price:20,sold:!1,_storeId:3,},{itemId:5,cost:2,price:10,sold:!1,_storeId:4,},{itemId:6,cost:10,price:50,sold:!0,_storeId:4,},]

const { Store, addItemToStoreMap, storesById } = storeUtils();

// Loop over the stores *once*, loop over the items *once*
// During the second loop, add items to the right stores
const itemsByStoreId = itemData.reduce(addItemToStoreMap, storesById(storeData));

console.log(Object.values(itemsByStoreId));

function storeUtils() {

  // Our client-side model for a Store
  const Store = ({ storeId, city, state }) => ({
    storeId,
    city,
    state,
    totalCost: 0,
    totalPrice: 0,
    countTotalItems: 0,
    countSoldItems: 0
  });

  // Merge logic for adding an item to a store
  // Can be used in a reduce on a list of items seeded with a store
  const addItemToStore = (store, item) => ({
    ...store,
    totalCost: store.totalCost + item.cost,
    totalPrice: store.totalPrice + item.price,
    countTotalItems: store.countTotalItems + 1,
    countSoldItems: store.countSoldItems + item.sold
  });

  // Selects the right store for an item and returns a new
  // map with the updated store
  const addItemToStoreMap = (storeMap, item) => ({
    ...storeMap,
    [item._storeId]: addItemToStore(storeMap[item._storeId], item)
  });

  // Converts raw data to Store objects and indexes them by their id
  const storesById = storeData => storeData.reduce(
    (map, sd) => Object.assign(map, { [sd.storeId]: Store(sd) }),
    {}
  );

  return { Store, addItemToStoreMap, storesById };
};