Как сопоставить массив объектов с новым массивом - PullRequest
0 голосов
/ 28 мая 2020

Как сопоставить массив объектов с новым массивом

От некоторого API я получаю такой ответ:

[
  {
    name: line1,
    values: [
      { clock: clock1, value: value1 },
      { clock: clock2, value: value2 },
      { clock: clock3, value: value3 },
      { clock: clock4, value: value4 }
    ]
  },
  {
    name: line2,
    values: [
      { clock: clock1, value: value5 },
      { clock: clock2, value: value6 },
      { clock: clock4, value: value7 }
    ]
  },
  {
    name: line3,
    values: [
      { clock: clock1, value: value8 },
      { clock: clock4, value: value9 }
    ]
  },
  {
    name: line4,
    values: [
      { clock: clock1, value: value10 },
      { clock: clock2, value: value11 },
      { clock: clock3, value: value12 },
      { clock: clock4, value: value13 },
      { clock: clock5, value: value14 }
    ]
  }
]

Все значения свойств clock: * одинаковы для всех объектов , поэтому clock1 из line1 равно clock1 из line2/3/4. Но свойства значений не равны.

Для моих целей мне нужно объединить объекты значений из всех строк в этот новый массив объектов:

[
  { clock: clock1, line1: value1, line2: value5, line3: value8, line4: value10 },
  { clock: clock2, line1: value2, line2: value6, line3: null,   line4: value11 },
  { clock: clock3, line1: value3, line2: null,   line3: null,   line4: value12 },
  { clock: clock4, line1: value4, line2: value7, line3: value9, line4: value13 },
  { clock: clock5, line1: null,   line2: null,   line3: null,   line4: value14 }
]

Ключи в новых объектах должны быть свойством name из исходных объектов.

Есть ли способ сделать это?

Ответы [ 5 ]

3 голосов
/ 28 мая 2020

Вы можете попробовать мой код:

enter image description here

let arr = [
    {
      name: "line1",
      values: [
        { clock: "clock1", value: "value1" },
        { clock: "clock2", value: "value2" },
        { clock: "clock3", value: "value3" },
        { clock: "clock4", value: "value4" }
      ]
    },
    {
      name: "line2",
      values: [
        { clock: "clock1", value: "value5" },
        { clock: "clock2", value: "value6" },
        { clock: "clock4", value: "value7" }
      ]
    },
    {
      name: "line3",
      values: [
        { clock: "clock1", value: "value8" },
        { clock: "clock4", value: "value9" }
      ]
    },
    {
      name: "line4",
      values: [
        { clock: "clock1", value: "value10" },
        { clock: "clock2", value: "value11" },
        { clock: "clock3", value: "value12" },
        { clock: "clock4", value: "value13" },
        { clock: "clock5", value: "value14" },
      ]
    }
  ],
  data = []

for (let i = 1; i <= 5; i++) {
  let obj = { clock: "clock" + i}
  arr.map((line) => {
    let clock = line.values.find(v => v.clock == "clock" + i)
    obj[line.name] = clock ? clock.value : null
  })
  data.push(obj)
}
console.log(data)
1 голос
/ 28 мая 2020

Я подозреваю, что создание 2D-массива объектов было бы намного проще, однако, если вам действительно нужно сделать это таким образом, вы можете перебирать строки и создавать новые ключи для каждой строки. В приведенном ниже примере я назвал свой входной массив «данными». Вы также можете посмотреть живой пример здесь

// store the longest set of values in the list as this seems to be what you want the
// object sizes to be.
let maxSize = Math.max.apply(Math, data.map(line => { return line.values.length }))

// create a new list to store the objects we'll create
let newList = [];

// loop through each line and insert it's values with the key corresponding to the line name.
data.forEach(line => {
    // loop through the values for this line
  for (i=0; i < maxSize; i++) {
    // handle case where we need to add more arrays to our list
    if (newList.length <= i) newList.push({});
    // check if this value exists or if we are just need to append null
    if (i < line.values.length) {
    newList[i][line.name] = line.values[i][Object.keys(line.values[i])[0]]
    } else { newList[i][line.name] = null }
  }
});
1 голос
/ 28 мая 2020

вы можете попробовать использовать концепцию, называемую хешированием, это объединит ваши значения в соответствии со значением clock.

   var hash = {};
   temp1.map((t0)=>{
       t0.values.map((t1)=>{
           if(hash[t1.clock]){
              hash[t1.clock][t0.name] = t1.value
           } else {
               hash[t1.clock] = {}
               hash[t1.clock][t0.name] = t1.value
           }
       })
   })

temp1 obj После того, как у вас будет ha sh значений теперь вы можете легко изменить его так, как вы хотите, поэтому скажем, вы хотите изменить ha sh в упомянутом вами объекте

   var clocks = []
   for(var key in hash){
       var newClockObj = {}    
       newClockObj['clock'] = key;
       for(var clockKey in hash[key]){
           newClockObj[clockKey] = hash[key][clockKey];
       }
       clocks.push(newClockObj)
   }

enter image description here

0 голосов
/ 28 мая 2020

Используйте forEach для перебора массива и их значений и построения объекта res. Сначала создайте объект empty, чтобы иметь нулевые значения по умолчанию.

const convert = (data) => {
  const empty = Object.fromEntries(data.map(({name}) => [name, null]));
  const res = {};
  data.forEach(({ name, values }) => {
    values.forEach(({ clock, value }) => {
      Object.assign(res[clock] = res[clock] || {...empty}, {
        clock,
        [name]: value,
      });
    });
  });
  return Object.values(res);
};

const data = [
  {
    name: "line1",
    values: [
      { clock: "clock1", value: "value1" },
      { clock: "clock2", value: "value2" },
      { clock: "clock3", value: "value3" },
      { clock: "clock4", value: "value4" },
    ],
  },
  {
    name: "line2",
    values: [
      { clock: "clock1", value: "value5" },
      { clock: "clock2", value: "value6" },
      { clock: "clock4", value: "value7" },
    ],
  },
  {
    name: "line3",
    values: [
      { clock: "clock1", value: "value8" },
      { clock: "clock4", value: "value9" },
    ],
  },
  {
    name: "line4",
    values: [
      { clock: "clock1", value: "value10" },
      { clock: "clock2", value: "value11" },
      { clock: "clock3", value: "value12" },
      { clock: "clock4", value: "value13" },
      { clock: "clock5", value: "value14" },
    ],
  },
];


console.log(convert(data));
0 голосов
/ 28 мая 2020

Этот не оптимизирован, но он работает со всеми данными вашего формата

let width = [];
let depth = [];
let result = [];

data.forEach(d => {
    if (width.indexOf(d.name) == -1) {
        width.push(d.name);
    }

    d.values.forEach(v => {
        if (depth.indexOf(v.clock) == -1) {
            depth.push(v.clock);
        }
    })
})

depth.forEach(d => {
    let temp = {
        clock: d
    };
    width.forEach(w => {
        temp[w] = null;
        data.forEach(dt => {
            if (dt.name == w) {
                dt.values.forEach(v => {
                    if (v.clock == d) {
                        temp[w] = v.value;
                    }
                })
            }
        })
    })

    result.push(temp);
})

console.log(result);

Результат

[
  {
    clock: 'clock1',
    line1: 'value1',
    line2: 'value5',
    line3: 'value8',
    line4: 'value10'
  },
  {
    clock: 'clock2',
    line1: 'value2',
    line2: 'value6',
    line3: null,
    line4: 'value11'
  },
  {
    clock: 'clock3',
    line1: 'value3',
    line2: null,
    line3: null,
    line4: 'value12'
  },
  {
    clock: 'clock4',
    line1: 'value4',
    line2: 'value7',
    line3: 'value9',
    line4: 'value13'
  },
  {
    clock: 'clock5',
    line1: null,
    line2: null,
    line3: null,
    line4: 'value14'
  }
]
...