Как вернуть массив данных из другого массива?

#javascript #arrays #object

#javascript #массивы #объект

Вопрос:

У меня есть данные массива, и после итерации я хочу получить новый массив с другой структурой

Это мой исходный массив:

 let oldArr = [
 {
  "20200714": [
    {      
      "StartDate": "2020-07-14T11:05:31.151687000",   
      "EndDate": "2020-07-14T12:11:59.673687000",                   
    },
    {      
      "StartDate": "2020-07-14T13:05:31.151687000",      
      "EndDate": "2020-07-14T14:11:59.673687000",                  
    },
  ],
  "20200715": [
    {         
      "StartDate": "2020-07-15T14:05:31.151687000",        
      "EndDate": "2020-07-15T15:11:59.673687000",                        
    }
  ]
 }
]
  

Вывод должен быть таким:

       [
        {
          x: '20200714',
          y: [          
            '2020-07-14T11:05:31.151687000',
            '2020-07-14T12:11:59.673687000',       
          ]              
        },
        {
          x: '20200714',
          y: [          
            '2020-07-14T13:05:31.151687000',
            '2020-07-14T13:05:31.151687000',       
          ]              
        },
        {
          x: '20200715',
          y: [          
            '2020-07-15T14:05:31.151687000',
            '2020-07-15T15:11:59.673687000',       
          ]              
        }           
      ]
  

Я пытаюсь выполнить итерацию массива с помощью map () что-то вроде этого, но я не знаю, как это сделать правильно

 let newArr = oldArr.map((key) => {
  return {
    x: key,
    y: [          
      key.StartDate,
      key.EndDate                 
    ]
  }
)
  

Заранее спасибо

Ответ №1:

Вам нужно объединить несколько редукторов для доступа к нужным данным:

 let oldArr = [
 {
  "20200714": [
    {      
      "StartDate": "2020-07-14T11:05:31.151687000",   
      "EndDate": "2020-07-14T12:11:59.673687000",                   
    },
    {      
      "StartDate": "2020-07-14T13:05:31.151687000",      
      "EndDate": "2020-07-14T14:11:59.673687000",                  
    },
  ],
  "20200715": [
    {         
      "StartDate": "2020-07-15T14:05:31.151687000",        
      "EndDate": "2020-07-15T15:11:59.673687000",                        
    }
  ]
 }
]

const newArr = oldArr.reduce((mainAcc, currItem) => [...mainAcc, ...Object.keys(currItem).reduce((acc, currKey) => {
  const vals = currItem[currKey];
  return [
    ...acc,
    vals.map((v) => ({ x: currKey, y: [v.StartDate, v.EndDate] })),
  ];
}, [])], []);

console.log(newArr);  

Комментарии:

1. Решение от Люка Сторри легче читать и потребует лишь небольшой адаптации, чтобы заставить его работать для всего массива. Решение, которое я опубликовал, работает с массивом как oldArr и будет учитывать каждый элемент массива. Вы должны пойти и попытаться реализовать что-нибудь на основе этого кода.

Ответ №2:

Ваш источник на самом деле представляет собой массив из одного объекта, поэтому вы хотите использовать Object.entries для получения массива, а затем выполнить цикл над этими записями с помощью вложенного цикла над внутренним массивом y значений.

Из-за трех вложенных циклов код упрощается, если вы просто создаете массив и нажимаете на него в forEach , а не вкладываете несколько reduce циклов:

 let oldArr = [{
  "20200714": [{
      "StartDate": "2020-07-14T11:05:31.151687000",
      "EndDate": "2020-07-14T12:11:59.673687000",
    },
    {
      "StartDate": "2020-07-14T13:05:31.151687000",
      "EndDate": "2020-07-14T14:11:59.673687000",
    },
  ],
  "20200715": [{
    "StartDate": "2020-07-15T14:05:31.151687000",
    "EndDate": "2020-07-15T15:11:59.673687000",
  }]
}]

let newArr = []
oldArr.forEach(outerObject => Object.entries(outerObject)
  .forEach(([key, items]) =>
    items.forEach((item) => newArr.push({
      x: key,
      y: [item.StartDate, item.EndDate]
    }))
  )
)

console.log(newArr)  

Комментарии:

1. зачем ограничиваться первым индексом? если это массив, то наверняка в нем есть другие элементы

2. Не «наверняка» — я использовал фрагмент кода из примера данных — третий вложенный цикл может не понадобиться.

3. если не более 1 элемента, ваш 3-й цикл не увеличит временную сложность, верно? Но если имеется более 1 элемента, ваше решение завершится неудачей

4. Дело не во временной сложности. У вас есть входные данные, вы хотите получить выходные. Входные данные могут содержать больше записей во внешнем массиве, а могут и нет — добавление другого вложенного редуктора для создания беспорядочной трехуровневой вложенности добавляет ненужную сложность коду, обычно лучше упростить его. Тем не менее, я обновил код, чтобы добавить дополнительную вложенность, но чтобы он выглядел проще, я изменил на forEach вместо reduce

Ответ №3:

Вы можете выполнить обычный for цикл для перебора ключей объекта. На самом деле это довольно просто:

 var obj = [{
    "20200714": [{
            "StartDate": "2020-07-14T11:05:31.151687000",
            "EndDate": "2020-07-14T12:11:59.673687000",
        },
        {
            "StartDate": "2020-07-14T13:05:31.151687000",
            "EndDate": "2020-07-14T14:11:59.673687000",
        },
    ],
    "20200715": [{
        "StartDate": "2020-07-15T14:05:31.151687000",
        "EndDate": "2020-07-15T15:11:59.673687000",
    }]
}];

var newObj = [];

for (var i = 0; i < obj.length; i  ) {
    var currentKeys = Object.keys(obj[i]);
    for (var j = 0; j < currentKeys.length; j  ) {
        for (var k = 0; k < obj[i][currentKeys[j]].length; k  ) {
            newObj.push({
                x: currentKeys[j],
                y: [obj[i][currentKeys[j]][k].StartDate, obj[i][currentKeys[j]][k].EndDate]
            });
        }
    }
}
  

newObj значение:

 [
  {
    "x": "20200714",
    "y": [
      "2020-07-14T11:05:31.151687000",
      "2020-07-14T12:11:59.673687000"
    ]
  },
  {
    "x": "20200714",
    "y": [
      "2020-07-14T13:05:31.151687000",
      "2020-07-14T14:11:59.673687000"
    ]
  },
  {
    "x": "20200715",
    "y": [
      "2020-07-15T14:05:31.151687000",
      "2020-07-15T15:11:59.673687000"
    ]
  }
]
  

Ответ №4:

я думаю, проблема в том, что у вас есть массив с одним объектом внутри. Итак, когда вы используете карту массива, ваш «ключ» — это позиция 0 массива, я думаю, вы можете сделать что-то подобное, чтобы получить ожидаемый результат:

 Object.keys(oldArr).reduce((acc, current) => {
    console.log(acc, current)
    oldArr[current].forEach((objWithDate) => {
        acc.push({
            x: current,
            y: [objWithDate.StartDate, objWithDate.EndDate]
        })
    })
    return acc
}, [])
  

я действительно не знаю вашу версию node или если это для Интернета, но я надеюсь, что это сработает для вас. хорошего дня