[英]Typescript mapping and or reduce: Map array to other Array type
I need to map an Array<Quote>
, where Quote
is:我需要映射一个Array<Quote>
,其中Quote
是:
export interface Quote {
readonly chronoUnit: Quote.ChronoUnitEnum;
readonly downloadedDocs: number;
readonly downloadedKb: number;
readonly uploadedKb: number;
readonly uploadedRefs: number;
}
export namespace Quote {
export type ChronoUnitEnum = 'HOUR' | 'DAY' | 'MONTH' | 'YEAR';
export const ChronoUnitEnum = {
HOUR: 'HOUR' as ChronoUnitEnum,
DAY: 'DAY' as ChronoUnitEnum,
MONTH: 'MONTH' as ChronoUnitEnum,
YEAR: 'YEAR' as ChronoUnitEnum
};
}
To an Array<AlignedQuote>
:到Array<AlignedQuote>
:
export interface AlignedQuote {
readonly alignedType: AlignedQuote.AlignedEnum;
readonly hour: number;
readonly day: number;
readonly month: number;
readonly year: number;
}
export namespace AlignedQuote {
export type AlignedEnum = 'DOWNLOADEDDOCS' | 'DOWNLOADEDKB' | 'UPLOADEDKB' | 'UPLOADEDREFS';
export const AlignedEnum = {
HOUR: 'DOWNLOADEDDOCS' as AlignedEnum,
DAY: 'DOWNLOADEDKB' as AlignedEnum,
MONTH: 'UPLOADEDKB' as AlignedEnum,
YEAR: 'UPLOADEDREFS' as AlignedEnum
};
}
I was thinking about using any kind of map
, but I don't quite figure out how.我正在考虑使用任何类型的map
,但我不太清楚如何。
let quotes: Array<Quote>;
let alignedQuotes: Array<AlignedQuotes> = quotes.map(???).reduce(????);
Example:例子:
quotes: [{
chronoUnit:ChronoUnit.HOUR,
downloadedDocs:1,
downloadedKb:23,
uploadedKb:65,
uploadedRefs:7
}];
alignedQuotes: [
{alignedType: AlignedQuote.AlignedEnum.DOWNLOADEDDOCS, hour: 1, day: null, month: null, year: null},
{alignedType: AlignedQuote.AlignedEnum.DOWNLOADEDKBS, hour: 23, day: null, month: null, year: null},
{alignedType: AlignedQuote.AlignedEnum.UPLOADEDKBS, hour: 65, day: null, month: null, year: null},
{alignedType: AlignedQuote.AlignedEnum.UPLOADEDREFS, hour: 7, day: null, month: null, year: null}
]
Any ideas?有任何想法吗?
I`m not sure how exactly your two objects are related, but you can check here how Array.Map() works with basic example.我不确定你的两个对象究竟是如何相关的,但你可以在这里查看 Array.Map() 如何与基本示例一起工作。 It is a function and you can do whatever you need inside the brackets这是一个函数,你可以在括号内做任何你需要的事情
Possible solution to your case:您的情况可能的解决方案:
let alignedQuotes: Array<AlignedQuotes> = quotes.map(quote => <AlignedQuotes>{
hour: quote.downloadedDocs,
day: null,
month: null,
year: null
});
quote
here is single Quote obj (.map iterates over all of them), you can use his properties when needed like in the 'hour' example.这里的quote
是单引号对象(.map 遍历所有对象),您可以在需要时使用他的属性,就像在 'hour' 示例中一样。
I would break down the problem into three parts.我会将问题分解为三个部分。
Based upon this example:基于这个例子:
{alignedType: AlignedQuote.AlignedEnum.DOWNLOADEDDOCS, hour: 1, day: null, month: null, year: null},
For the above, DOWNLOADEDDOCS
is the plucker of which property to read, and hour
is the selector of which quotes to iterate and 1
is the sum.对于上述, DOWNLOADEDDOCS
是读取哪个属性的选择器, hour
是要迭代的引用的选择器, 1
是总和。 You need to use four different selectors to get all of hour
, day
, month
and year
for a single AlignedQuote
.您需要使用四个不同的选择器来获取单个AlignedQuote
所有hour
、 day
、 month
和year
。
So we write each of the above as separate functions.所以我们把上面的每一个都写成单独的函数。
const plucker = (quote: Quote, x: AlignedQuote.AlignedEnum): number => quote[x];
const selector = (quotes: Quote[], x: Quote.ChronoUnitEnum): Quote[] => quotes.filter(q => q.chronoUnit === x);
const sum = (nums: number[]): number => nums.reduce((acc, next) => acc + next, 0);
We want to use the above to produce a single row like this:我们想使用上面的内容来生成这样的一行:
{alignedType: AlignedQuote.AlignedEnum.DOWNLOADEDDOCS, hour: 1, day: null, month: null, year: null},
Which can be written like this:可以这样写:
const hours = {
alignedType: AlignedQuote.AlignedEnum.HOUR,
hour: sum(selector(quotes, ChronoUnitEnum.HOUR).map(q => pluck(q, AlignedEnum.HOUR))),
day: null,
month: null,
year: null
};
Now we want to produce the above for each hour
, day
, month
and year
.现在我们要为hour
、 day
、 month
和year
生成上述内容。
const nulls = {hour: null, day: null, month: null, year: null};
const totals = [
[AlignedQuote.AlignedEnum.HOUR, ChronoUnitEnum.HOUR],
[AlignedQuote.AlignedEnum.DAY, ChronoUnitEnum.DAY],
[AlignedQuote.AlignedEnum.MONTH, ChronoUnitEnum.MONTH],
[AlignedQuote.AlignedEnum.YEAR, ChronoUnitEnum.YEAR]
].map(([alignedType, unit]: [AlignedQuote.AlignedEnum, ChronoUnitEnum]) => {
const values = {
alignedType,
[unit]: sum(selector(quotes, unit).map(q => pluck(q, alignedType)))
};
return {...nulls, ...values};
});
The above only works if the enum values match the letter case of the property fields.以上仅适用于枚举值与属性字段的字母大小写匹配的情况。 Otherwise, you'll have to add functions that convert the enum to a property field name (which is just a simple object map).否则,您必须添加将枚举转换为属性字段名称的函数(这只是一个简单的对象映射)。 But, to save time of posting an answer I just modified the enums.但是,为了节省发布答案的时间,我只是修改了枚举。
Like this:像这样:
export namespace Quote {
export type ChronoUnitEnum = 'hour' | 'day' | 'month' | 'year';
export const ChronoUnitEnum = {
HOUR: 'hour' as ChronoUnitEnum,
DAY: 'day' as ChronoUnitEnum,
MONTH: 'month' as ChronoUnitEnum,
YEAR: 'year' as ChronoUnitEnum
};
}
export namespace AlignedQuote {
export type AlignedEnum = 'downloadedDocs' | 'downloadedKb' | 'uploadedKb' | 'uploadedRefs';
export const AlignedEnum = {
HOUR: 'downloadedDocs' as AlignedEnum,
DAY: 'downloadedKb' as AlignedEnum,
MONTH: 'uploadedKb' as AlignedEnum,
YEAR: 'uploadedRefs' as AlignedEnum
};
}
I was able to solve your example with a reduce.我能够用reduce来解决你的例子。 You can take a look at the following code (I removed some types for the example).您可以查看以下代码(我为示例删除了一些类型)。 It's not the solution but maybe a good lead.这不是解决方案,但可能是一个很好的线索。
const quotes = [{
chronoUnit: 'hour',
downloadedDocs:1,
downloadedKb:23,
uploadedKb:65,
uploadedRefs:7
}];
const alignedQuotes = [
{alignedType: 'DOWNLOADEDDOCS', hour: 1, day: null, month: null, year: null},
{alignedType: 'DOWNLOADEDKBS', hour: 23, day: null, month: null, year: null},
{alignedType: 'UPLOADEDKBS', hour: 65, day: null, month: null, year: null},
{alignedType: 'UPLOADEDREFS', hour: 7, day: null, month: null, year: null}
]
return quotes.reduce((acc, item) => {
const quote = Object.keys(item).filter(key => key !== 'chronoUnit').map(key => {
return {
alignedType: key.toUpperCase(),
hour: item['chronoUnit'] === 'hour' ? item[key] : null,
day: item['chronoUnit'] === 'day' ? item[key] : null,
month: item['chronoUnit'] === 'month' ? item[key] : null,
year: item['chronoUnit'] === 'year' ? item[key] : null,
}
})
return acc.concat(quote);
}, []);
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.