首页 > 解决方案 > 如何在 TypeScript 中进行投影?

问题描述

我想填充orderstype 的数组Order。预期的结果是orders=[{id:1,qt:4},{id:2, qt:2},{id:3,qt:2}]。如何在 TypeScript 中这样做?我是新手。

export class Product {
  constructor(public id: number, public name: string, public price: number) {}
}
export interface Order {
  id: number;
  qt: number;
}

export const products: Product[] = [
  new Product(1, 'Apple', 2.1),
  new Product(2, 'Banana', 2.2),
  new Product(3, 'Chocolate', 2.3),
  new Product(4, 'Dessert', 2.4),
];

export const cart: Product[] = [
  products[0],
  products[0],
  products[2],
  products[1],
  products[2],
  products[0],
  products[1],
  products[0],
];

export const orders: Order[] = [];

编辑

对于那些想知道如何 orders=[{id:1,qt:4},{id:2, qt:2},{id:3,qt:2}]获得的人。

cart

所以通过使用购物车,我必须获得orders=[{id:1,qt:4},{id:2, qt:2},{id:3,qt:2}]. 应该很清楚。

标签: javascripttypescript

解决方案


由于您正在寻找“类似 LINQ”的解决方案,因此您可能想要使用更高阶的函数,例如map// filterreduce

严格来说,您的问题不能仅通过 LINQ 投影来解决。这些仅表示map( Select)、concatMap/ flatMap( SelectMany) 和zip( Zip)。您的问题涉及计算id整个数组中每个的出现次数。

几乎每个数据操作问题都可以通过更高阶的折叠来解决,即reduce在 javascript 领域,Aggregate在 C# 领域。这个也不例外。首先要做的是计算每个 的出现次数id,并构建一个计数器对象

cart.reduce((acc, { id }) => {
    acc[id] = (acc[id] ?? 0) + 1;
    return acc;
}, {} as Record<number, number>);

本质上,您从一个空对象开始折叠操作,然后添加每个对象id及其出现次数。每次id在数组中遇到an 时cart,都会增加它在对象中的计数。如果id累积对象中不存在 ,则无效合并 ( acc[id] ?? 0) 使用0并增加它。

这会给你——

{ '1': 4, '2': 2, '3': 2 }

现在,你需要把它变成——

[ { id: 1, qt: 4 }, { id: 2, qt: 2 }, { id: 3, qt: 2 } ]

为此,使用Object.entries折叠结果来获得 -

> Object.entries({ '1': 4, '2': 2, '3': 2 })
[ [ '1', 4 ], [ '2', 2 ], [ '3', 2 ] ]

最后,一个简单map的就是你所需要的——

Object.entries(...).map(([id, qt]) => ({ id: Number(id), qt }))

结合所有这些,你有 -

export const orders: Order[] = Object.entries(
    cart.reduce((acc, { id }) => {
        acc[id] = (acc[id] ?? 0) + 1;
        return acc;
    }, {} as Record<number, number>)
).map(([id, qt]) => ({ id: Number(id), qt }));

这里要注意的一件事Object.entries是效率非常低,因为它构建了一个数组而不是迭代器。如果您想提高效率,请Object.entries使用生成器函数滚动迭代器版本并使用它-

function* objEntries<T>(x: Record<string, T>): IterableIterator<[string, T]> {
  for (const k in x) {
    yield [k, x[k]];
  }
}

推荐阅读