将不同的属性展平为单个数组

时间:2018-03-12 04:18:00

标签: javascript ecmascript-6

我有一个javascript对象文字,如下所示。

    data: {
       prop1ByZones:[{zone: "Zone1", x: 1}, {zone: "Zone2", x: 5}],
       prop2ByZones:[{zone: "Zone1", y: "1302.5"}],
       prop3ByZones:[{zone: "Zone2", z: 2}]
    }

输出应该像 -

output: [{zone: "Zone1", x: 1, y: "1302.5", z: 0}, {zone: "Zone2", x: 5, y: 0, z: 2}]

我可以用琐碎的方式做到这一点,比如首先添加prop1ByZones进行输出,然后循环通过prop2ByZones和prop3ByZones并检查现有区域。如果区域在那里然后更新它,否则添加它。

我只是想检查是否有任何优雅的方式。请告诉我。

3 个答案:

答案 0 :(得分:0)

一种可能的方法:

<ion-split-pane when="md">
    <ion-menu [content]="content">

        <ion-header>
            <ion-toolbar>
                <ion-title>{{gmaildata.displayName}}</ion-title>
            </ion-toolbar>
        </ion-header>

        <ion-content class="no-scroll">
            <ion-list>
                <button menuClose ion-item *ngFor="let p of pages" (click)="openPage(p)" style="padding-left:5px" [style.color]="p.iconcolor === 'primary'?'#488aff':''">
                    <ion-icon [name]="p.icon" item-left color="{{p.iconcolor}}"></ion-icon> {{p.title}}
                </button>
            </ion-list>
        </ion-content>

    </ion-menu>
    <ion-nav [root]="rootPage" #content swipeBackEnabled="false" main></ion-nav>
</ion-split-pane>
var data = { prop1ByZones:[{zone: "Zone1", x: 1}, {zone: "Zone2", x: 5}], prop2ByZones:[{zone: "Zone1", y: "1302.5"}], prop3ByZones: [{zone: "Zone2", z: 2}] }

var arr = [...data.prop1ByZones, ...data.prop2ByZones, ...data.prop3ByZones]
var resp = arr.reduce((acc, { zone, x, y, z }) => {
  var prev = acc.find(x => zone == x.zone);
  if(prev) {
    prev.x = x ? x : prev.x,
    prev.y = y ? y : prev.y,
    prev.z = z ? z : prev.z
    return acc;
  }
  return acc.concat({zone: zone, x: x ? x : 0, y: y ? y : 0, z: z ? z : 0});
}, []);

console.log(resp)

答案 1 :(得分:0)

这是一种方法(使用lodash进行迭代),你可以将条件优化为三元组等,但这会给你输出:

const data = {
       prop1ByZones:[{zone: "Zone1", x: 1}, {zone: "Zone2", x: 5}],
       prop2ByZones:[{zone: "Zone1", y: "1302.5"}],
       prop3ByZones:[{zone: "Zone2", z: 2}]

};

let list = {};
_.each(data, (d, i) => {
   _.each(d, (e) => {
     const zone = e.zone;

     if (!list[zone]) {
       list[zone] = zone;
       list[zone] = {};
     }

     if (!list[zone].x) {
        list[zone].x = e.x || 0;  
     }

     if (!list[zone].y) {
        list[zone].y = e.y || 0;  
     }

     if (!list[zone].z) {
        list[zone].z = e.z || 0;  
     }

   });

});
// put everything in an array
let result = [];
_.each(list, (obj, k) => {
  result.push({
    zone: k,
    x: obj.x,
    y: obj.y,
    z: obj.z
  });
});

console.log(result);

答案 2 :(得分:0)

您可以Object.values()spreading展平为Array.concat(),然后将reduce数组展平为Map,并展开Map.values() defaultdict迭代器返回数组:

&#13;
&#13;
const data = {
   prop1ByZones:[{zone: "Zone1", x: 1}, {zone: "Zone2", x: 5}],
   prop2ByZones:[{zone: "Zone1", y: "1302.5"}],
   prop3ByZones:[{zone: "Zone2", z: 2}]
}

const result = [... // spread the map values iterator (see end) back to an array
  [].concat(...Object.values(data)) // get the object's values and flatten to a single array
  .reduce( // reduce the array to a Map
    // add the zone key to the map, and include the previous and current item
    (r, o) => r.set(o.zone, { ...(r.get(o.zone) || {}), ...o }), 
    new Map()
  ).values()] // get the map values iterator
  
console.log(result)
&#13;
&#13;
&#13;