将对象数组转换为不同的对象数组 - Javascript / Angular

8
我有一个看起来像这样的对象数组。我使用lodash中的.groupBy使其呈现出这种形式。
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,即使我尝试放置一个没有for循环的元素,我仍然会得到以下错误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
        ])
      );
    }
  }

使用lodash的.groupBy方法后打印结果的控制台日志 按国家分组的对象

1
你好,欢迎来到StackOverflow。目前来看,STATES数组是无效的。它应该是一个对象数组吗?还是一个单一的对象,包含值“USA”,“Canada”等。 - user184994
1
好的,请问您能否编辑您的问题,以便代码可以编译?谢谢。 - user184994
1
不,那仍然无法编译。你可以尝试在从lodash返回的对象上调用JSON.stringify,这会有所帮助。 - user184994
@user184994 最后,是我的错。我试图重新创建在控制台中打印的对象。我已经更新了我的问题。 - user10271701
@user184994,我已经发布了一张图片的链接,这样你就可以看到在使用lodash的.groupBy后打印出来的原始结构。谢谢。 - user10271701
显示剩余2条评论
2个回答

13
你可以使用数组的 map 函数来转换它们的结构。
下面的代码应该将它转换成你想要的结构。您可以单击“运行代码片段”以查看输出。

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,但不确定该如何操作。谢谢! - user10271701

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,它会抛出错误:[ts] Property 'push' does not exist on type 'Object'。你有没有其他的解决方法来避免这个警告? - user10271701
有趣。试试我刚刚添加的“长”版本。 - Akrion
有一个叫做Automapper的工具,如果你也有 .Net 经验的话,使用它会很容易... https://www.npmjs.com/package/automapper-ts - Gani Lastra

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接