1

I have an array of objects with an "asymetric" structure where keys are not the same and there are some nested object. I need loop through this:

  obj = [{
      "d14042018": {
        "date": "14-04-2018",
        "value": 5
      },
      "d02042018": {
        "date": "02-04-2018",
        "value": 10
      },
      "name": "my name"
    },
    {
      "d14042018": {
        "date": "14-04-2018",
        "value": 15
      },
      "d02042018": {
        "date": "02-04-2018",
        "value": 25
      },
      "name": "my second name"
    }]

what i need is to return a structure like this

first row = my name 5 10

second row = my second name 15 25

I tried a for in a custom Pipe...

    import { Pipe, PipeTransform } from '@angular/core';
    @Pipe({
      name: 'keys'
    })
    export class KeysPipe implements PipeTransform {

      transform(value: any, args?: any): any {
        let keys: string;

        if (value) {
          for (var prop in value) {
      
            if(typeof value[prop] != 'object') {
               keys = value[prop];
            } else {
              for (var subprop in prop) {
                keys = prop.subprop;
              }
            }
          }
        }
        return keys;
      }
    }

but id doesn't work...

can someone help?

M.Hajavi
  • 277
  • 4
  • 17
  • The key name is always there, but the date as you guess could change... so i can't know the name of the date keys – Gael Sapori Apr 16 '18 at 19:42
  • Such a poor design: anyway, if you capture the keys (regardless of value) with `Object.keys()` then you have something you can iterate over. If the structure stays the same you can use the key index to gather the `value` and the next key to get the second value, and the third key (name) to get the name. – Randy Casburn Apr 16 '18 at 19:45

2 Answers2

1

I'd recommend avoid using a Pipe for this type of advanced data manipulation and instead just generate the necessary data structure for display/usage in something like ngOnInit() or prior to binding to a public variable. You can use Object.keys() in combination with Array.prototype.map(), Array.prototype.join() and ternary statements to generate the data rows.

TypeScript:

this.rows = Object.keys(obj).map(key => {
  const o = this.data[key];
  const { name } = o;
  const values = Object.keys(o)
                   .map(k => o[k]['value'])
                   .join(' ');

  return { name, values };
});

HTML:

<ul>
  <li *ngFor="let row of rows">{{row.name}} {{row.values}}</li>
</ul>

Here is an example in action.

Hopefully that helps!

Alexander Staroselsky
  • 37,209
  • 15
  • 79
  • 91
0

An option is to reduce each object's keys to an array, then just join if you want each item to be a string:

const obj = [...]; // your example array
const flattened = obj.map(
    o => Object.keys(o).reduce(
        (acc,cur) => cur === 'name' 
            ? [o[cur], ...acc] // key is 'name', push value to first
            : [...acc, o[cur].value] // other than name, push value of value last
        , []).join(' ')
    );
funkizer
  • 4,626
  • 1
  • 18
  • 20