【问题标题】:Transform array of objects to a different array of objects - Javascript/Angular将对象数组转换为不同的对象数组 - Javascript/Angular
【发布时间】:2018-08-25 06:45:00
【问题描述】:

我有一个看起来像这样的对象数组。我使用 .groupBy 和 lodash 使它看起来像这样。

States.ts

STATES: Object[] = [
  {
    USA: [
      {
        name: 'Alabama',
        abbreviation: 'AL',
        country: 'USA'
      },
      {
        name: 'Alaska',
        abbreviation: 'AK',
        country: 'USA'
      }
    ]
  },
  {
    Canada: [
      {
        name: 'Alberta',
        abbreviation: 'ALB',
        country: 'Canada'
      }
    ]
  }
];

我需要它看起来像这样:

    stateList:StateDropdownItem[] =[ 
    {
       label: 'USA', 
       items: [
               {label: 'AL', value: 'Alabama'},
               {label: 'AK', value: 'Alaska'},
       ]
    },
    .
    .
   ]

我已经尝试了下面的代码,但它不起作用。当我将它打印到控制台时出现undefiened,即使我尝试在没有forloop的情况下放置一个元素,我也会收到以下错误Cannot read property 'push' of undefined

TS

dropdownOfStates: StateDropdownItem[];
.
.
dropdownBuilder() {
    const STATES_BY_COUNTRY = this.getStatesByCountry();
    let tempItem;
    for (let i = 0; i < STATES_BY_COUNTRY.length; i++) {
      tempItem = STATES_BY_COUNTRY[i];
      this.dropdownOfStates.push(
        new StateDropdownItem('KEY COUNTRY VALUE HERE', [
          tempItem.abbreviation,
          tempItem.name
        ])
      );
    }
  }

打印使用 .groupBy 和 lodash 的结果后的 Console.log groupby objects by country

【问题讨论】:

  • 嗨,欢迎来到 StackOverflow。就目前而言,STATES 数组无效。它应该是一个对象数组吗?或具有值USACanada 等的单个对象
  • 这是一个 State 类型模块的数组,我在一个名为 state.module.ts export class State { abbreviation: string; name: string; country: string; constructor(abbreviation: string, name: string, country: string) { this.abbreviation = abbreviation; this.name = name; this.country = country; } }的文件中创建
  • 好的,您能否编辑您的问题以便编译代码?谢谢
  • @user184994 完成
  • 不,那仍然无法编译。您可以尝试在从 lodash 返回的对象上调用 JSON.stringify,这会有所帮助。

标签: javascript angular typescript lodash


【解决方案1】:

您可以使用数组的map 函数来转换它们的结构。

下面的代码应该将其转换为您想要的结构。可以点击“Run code sn -p”查看输出

let states = [
  {
    USA: [
      {
        name: 'Alabama',
        abbreviation: 'AL',
        country: 'USA'
      },
      {
        name: 'Alaska',
        abbreviation: 'AK',
        country: 'USA'
      }
    ]
  },
  {
    Canada: [
      {
        name: 'Alberta',
        abbreviation: 'ALB',
        country: 'Canada'
      }
    ]
  }
];

// Use the code below to transform 

let res = states.map((val) => {
  let country = Object.keys(val)[0]; // Get the name of the country, e.g. USA
  return { // Return the new object structure
    label: country,
    items: val[country].map((item) => ({label: item.abbreviation, value: item.name}))
  }
});

// Log the value
console.log(res);

【讨论】:

  • 非常感谢!你是个天才。我正在考虑使用 .map 但我不确定如何去做。谢谢!!
【解决方案2】:

这里是使用 ES6 和 reduceObject.keysmap 执行此操作的更简洁的方法:

var data = [ { USA: [ { name: 'Alabama', abbreviation: 'AL', country: 'USA' }, { name: 'Alaska', abbreviation: 'AK', country: 'USA' } ] }, { Canada: [ { name: 'Alberta', abbreviation: 'ALB', country: 'Canada' } ] } ];

const result = data.reduce((r,c) => Object.keys(c).map(x => r.push({ label: x, items: c[x].map(y => ({label: y.abbreviation, value: y.name }))})) && r, [])

console.log(result)

这是扩展的变体:

var data = [ { USA: [ { name: 'Alabama', abbreviation: 'AL', country: 'USA' }, { name: 'Alaska', abbreviation: 'AK', country: 'USA' } ] }, { Canada: [ { name: 'Alberta', abbreviation: 'ALB', country: 'Canada' } ] } ];

const result = data.reduce((r,c) => {
   Object.keys(c).map(x => {
     r.push({ label: x, items: c[x].map(y => ({label: y.abbreviation, value: y.name }))})})
	return r}, [])

console.log(result)

【讨论】:

  • Akrion,您的解决方案可以正常编译和运行。不幸的是 TSlint 不喜欢 r.push TSlint thorws 错误:[ts] 属性 'push' 在类型 'Object' 上不存在。您对此警告有替代方案吗?
  • 有趣。试试我刚刚添加的“更长”版本。
  • 有 Automapper,如果你也有 .Net 经验,使用它会很容易...npmjs.com/package/automapper-ts
猜你喜欢
  • 2019-10-22
  • 2017-01-14
  • 1970-01-01
  • 2016-04-19
  • 2021-09-24
  • 2019-05-17
  • 2021-01-07
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多