Создайте массив объектов из другого массива объектов с помощью фиктивного объекта - PullRequest
3 голосов
/ 30 января 2020

Я хотел бы создать массив объектов из другого массива объектов для построения графика.

Это массив, который я использую для размещения позиции объекта внутри ожидаемого объекта.

let uniqueSkills = ['Using', 'Analyzing', 'Summarizing', 'Inferring', 'Predicting', 'Activating']

Это мой объект, который необходимо изменить.

let data = {
      data0:[
        {count: 1, length: 1, skill: "Activating"},
        {count: 4, length: 1, skill: "Using"},
        {count: 2, length: 1, skill: "Analyzing"}
      ],
      data1: [
        {count: 2, length: 1, skill: "Summarizing"}
      ],
      data2: [
        {count: 1, length: 1, skill: "Predicting"},
        {count: 4, length: 1, skill: "Analyzing"}
      ]
    }

Конечный объект результата должен выглядеть следующим образом.

data = {
      data0:[
        {count: 4, length: 1, skill: "Using"},
        {count: 2, length: 1, skill: "Analyzing"},
        {skill: "Summarizing"},
        {skill: "Inferring"},
        {skill: "Predicting"},
        {count: 4, length: 1, skill: "Activating"}

      ],
      data1: [
        {skill: "Using"},
        {skill: "Analyzing"},
        {count: 2, length: 1, skill: "Summarizing"},
        {skill: "Inferring"},
        {skill: "Predicting"},
        {skill: "Activating"}
      ],
      data2: [
        {skill: "Using"},
        {count: 4, length: 1, skill: "Analyzing"},
        {skill: "Summarizing"},
        {skill: "Inferring"},
        {count: 1, length: 1, skill: "Predicting"},
        {skill: "Activating"}
      ]
    }

Алгоритм, который я написал, в некоторых случаях работает нормально, но в некоторых ломается. Вот оно,

Object.keys(data).forEach(key => {      
      for (let i = 0; i < uniqueSkills.length; i++) {       
        if (typeof data[key][i] == 'object') {      
          if (data[key][i].skill !== uniqueSkills[i]) {     
            let index = uniqueSkills.indexOf(data[key][i].skill)
            if (typeof data[key][index] == 'object') {
              let anotherIndex = uniqueSkills.indexOf(data[key][index].skill)
              let elementAtIndex = data[key][index]
              let elementAtAnotherIndex = data[key][anotherIndex]
              data[key][i] = elementAtIndex
              data[key][index] = elementAtAnotherIndex
            }
            else {
              data[key][index] = data[key][i]
              data[key][i] = {skill: uniqueSkills[i]}
            }
          }
        } else {        
          data[key][i] = {skill: uniqueSkills[i]}       
        }       
      }     
    })

Ответы [ 2 ]

4 голосов
/ 30 января 2020

Вы можете использовать Map, чтобы сначала создать как пустой шаблон с только skill свойствами в объектах, а затем заполнить Map фактическими данными, которые у вас есть. Object.entries и Object.fromEntries могут использоваться для преобразования простого объекта в массив и наоборот.

Поскольку Map сохраняет порядок вставки, порядок вывода будет гарантирован.

let uniqueSkills = ['Using', 'Analyzing', 'Summarizing', 'Inferring', 'Predicting', 'Activating']
let data = {data0:[{count: 1, length: 1, skill: "Activating"},{count: 4, length: 1, skill: "Using"},{count: 2, length: 1, skill: "Analyzing"}],data1: [{count: 2, length: 1, skill: "Summarizing"}],data2: [{count: 1, length: 1, skill: "Predicting"},{count: 4, length: 1, skill: "Analyzing"}]};

let newData = Object.fromEntries(Object.entries(data).map(([k, arr]) =>
    [k, Array.from(arr.reduce(
        (map, o) => map.set(o.skill, o),
        new Map(uniqueSkills.map(skill => [skill, { skill }]))
    ).values())]
));

console.log(newData);

Обратите внимание, что это решение имеет наихудший случай O (n²) сложность времени (с точки зрения длины uniqueSkills). Ваше собственное решение имеет временную сложность O (n³) , с двумя внешними циклами (forEach и for) и вложенным вызовом indexOf, что также представляет собой oop. Другие решения, которые вместо indexOf имеют вложенный find или findIndex, также имеют временную сложность O (n³) . Использование Map#get вместо одного из этих методов массива снижает сложность до O (n²) .

Это решение не изменяет исходный объект data. Он производит новый объект. Однако новый объект будет по-прежнему включать исходные объекты, найденные в исходных массивах data.

Проблема с вашим решением состоит в том, что вы идете по пути i, index, anotherIndex, пытаясь переместить объект, который стоит на пути к объекту, который вы хотите вставить. Но этот путь может быть еще длиннее. Эта «прогулка» по созданию пропусков, переходу к следующей позиции, созданию пропуска там, ... et c, априори не ограничена по длине.

2 голосов
/ 30 января 2020

Для каждого объекта в данных вызовите Array.prototype.map для uniqueSkills и найдите объект. вернуть объект, если найден, вернуть новый, если нет.

и заменить массив источником.

let uniqueSkills = ['Using', 'Analyzing', 'Summarizing', 'Inferring', 'Predicting', 'Activating']
let data = {data0:[{count: 1, length: 1, skill: "Activating"},{count: 4, length: 1, skill: "Using"},{count: 2, length: 1, skill: "Analyzing"}],data1: [{count: 2, length: 1, skill: "Summarizing"}],data2: [{count: 1, length: 1, skill: "Predicting"},{count: 4, length: 1, skill: "Analyzing"}]};

Object.keys(data).forEach(key => {
  data[key] =
    uniqueSkills.map(skill => data[key].find(e => e.skill === skill) || { skill });
});

console.log(data);
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...