Перебор сгруппированного объекта в Typescript

#javascript #typescript #ecmascript-6 #lodash

#javascript #typescript #ecmascript-6 #Lodash

Вопрос:

У меня есть объект с сгруппированными данными, сопоставленными с помощью функции Lodash groupBy, какой был бы наилучший способ выполнить итерацию по коллекции и получить следующую информацию:

  • totalProductNumber,
  • totalProductSum = Сумма(productsNumberInGroup * цена)
  • productsNumberPerGroup

Таким образом, результат может быть

 let result = {
totalProductNumber: 8,
totalProductSum: 17,
productsNumberPerGroup: [{1:2}, {2:3}, {3:3}] // or sth. like this
}
  
 interface IProduct {
  name: string;
  color: string;
  price: string;
 id: number
 }

    const products = {
  "1": [{
      "name": "Jim",
      "color": "blue",
      "price": 1,
      "id": 1
    },
    {
      "name": "Jim",
      "color": "blue",
      "price": 1,
      "id": 1
    }
  ],
  "2": [{
      "name": "Eddie",
      "color": "green",
      "price": 2,
      "id": 2
    },
    {
      "name": "Eddie",
      "color": "green",
      "price": 2,
      "id": 2
    },
    {
      "name": "Eddie",
      "color": "green",
      "price": 2,
      "id": 2
    }
  ],
  "3": [{
      "name": "Ela",
      "color": "pink",
      "price": 3,
      "id": 3
    },
    {
      "name": "Ela",
      "color": "pink",
      "price": 3,
      "id": 3
    },
    {
      "name": "Ela",
      "color": "pink",
      "price": 3,
      "id": 3
    }
  ]
}

  

Я предполагаю использовать Object.entries или Object.values

   let totalSum: number;
  let totalPrices: number[];
Object.values(products)
      .map((prod) => {
        (prod as IProduct[]).map((p) => {
            this.totalPrices.push(Number(p.price)); // here getting Cannot read property 'push' of undefined
        });
      });

  

Комментарии:

1. Вы только объявили totalPrices, вы не присвоили ему значение. Попробуйте присвоить ему пустой массив.

Ответ №1:

С изменяемым стилем

 interface IProduct {
  name: string
  color: string
  price: number
  id: number
}

type Products = Record<string, IProduct[]>

const products: Products = { ... }

let totalProductNumber = 0
let totalProductSum = 0
let productsNumberPerGroup: [string, number][] = []

Object.entries(products).map(([grpId, grpProducts]) => {
  totalProductNumber = totalProductNumber   grpProducts.length
  totalProductSum = totalProductSum   grpProducts.reduce((acc, curr) => acc   curr.price, 0)
  productsNumberPerGroup = [...productsNumberPerGroup, [grpId, grpProducts.length]]
})

console.log(totalProductNumber) // 8
console.log(totalProductSum) // 17
console.log(productsNumberPerGroup) //[ [ '1', 2 ], [ '2', 3 ], [ '3', 3 ] ]

  

С неизменяемым стилем

 
type Result = [
  totalProductNumber: number,
  totalProductSum: number,
  productsNumberPerGroup: [string, number][]
]
const initial: Result = [0, 0, []]

const [totalNum, totalSum, prdPerGrp] = Object.entries(products).reduce<Result>(
  ([num, sum, perGrp], [grpId, grpProducts]) => {
    return [
      num   grpProducts.length,
      sum   grpProducts.reduce((acc, curr) => acc   curr.price, 0),
      [...perGrp, [grpId, grpProducts.length]]
    ]
  },
  initial
)

console.log(totalNum) // 8
console.log(totalSum) // 17
console.log(prdPerGrp) // [ [ '1', 2 ], [ '2', 3 ], [ '3', 3 ] ]
  

Ответ №2:

Вы должны сделать два изменения

 let totalPrices: number[];
  

Для

 let totalPrices: number[] = [];
  

Еще одно изменение в интерфейсе

 interface IProduct {
  name: string;
  color: string;
  price: string;
  id: number
}
  

изменить

 price: string;
  

Для

 price: number;