打字稿映射和/或归约:将数组映射到其他数组类型

时间:2019-08-21 11:20:00

标签: typescript

我需要映射一个'debug_blacklist' => [ '_ENV' => [ 'APP_KEY', 'DB_DATABASE', 'DB_PASSWORD', 'DB_USERNAME', 'REDIS_PASSWORD', 'MAIL_PASSWORD', 'PUSHER_APP_KEY', 'PUSHER_APP_SECRET', ], '_SERVER' => [ 'APP_KEY', 'DB_DATABASE', 'DB_PASSWORD', 'DB_USERNAME', 'REDIS_PASSWORD', 'MAIL_PASSWORD', 'PUSHER_APP_KEY', 'PUSHER_APP_SECRET', ], '_POST' => [ 'password', ], ], ,其中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 }; }

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 }; } ,但我不太清楚如何使用。

map

示例:

let quotes: Array<Quote>;
let alignedQuotes: Array<AlignedQuotes> = quotes.map(???).reduce(????);

有什么想法吗?

3 个答案:

答案 0 :(得分:0)

我不确定两个对象之间的确切关联,但是您可以在此处检查Array.Map()如何与基本示例一起使用。这是一项功能,您可以在方括号内做任何事情

Click

可能的解决方案:

let alignedQuotes: Array<AlignedQuotes> = quotes.map(quote => <AlignedQuotes>{ 
     hour: quote.downloadedDocs,
     day: null, 
     month: null, 
     year: null
});

quote是单个Quote obj(.map遍历所有对象),您可以在需要时使用其属性,例如“ hour”示例。

答案 1 :(得分:0)

我将问题分为三个部分。

  • 拔毛器
  • 选择器
  • 一个夏天

基于此示例:

{alignedType: AlignedQuote.AlignedEnum.DOWNLOADEDDOCS, hour: 1, day: null, month: null, year: null},

对于上述情况,DOWNLOADEDDOCS是要读取哪个属性的拔节器,hour是要迭代引用的选择器,而1是总和。您需要使用四个不同的选择器来为单个hour获取所有daymonthyearAlignedQuote

因此,我们将上述每个功能编写为单独的函数。

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);

我们想使用上面的代码生成这样的一行:

{alignedType: AlignedQuote.AlignedEnum.DOWNLOADEDDOCS, hour: 1, day: null, month: null, year: null},

可以这样写:

const hours = {
    alignedType: AlignedQuote.AlignedEnum.HOUR,
    hour: sum(selector(quotes, ChronoUnitEnum.HOUR).map(q => pluck(q, AlignedEnum.HOUR))),
    day: null,
    month: null,
    year: null
};

现在,我们想为每个hourdaymonthyear生成以上内容。

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};
});

仅当枚举值与属性字段的字母大小写匹配时,以上内容才有效。否则,您将不得不添加将枚举转换为属性字段名称的函数(这只是一个简单的对象映射)。但是,为了节省发布答案的时间,我只修改了枚举。

赞:

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
    };
}

答案 2 :(得分:0)

我能够用简化的方式解决您的示例。您可以看一下以下代码(我为示例删除了一些类型)。这不是解决方案,但可能是一个很好的线索。

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);
}, []);