Перестановка массива так, чтобы ключи имели значения

#javascript #arrays #javascript-objects

Вопрос:

У меня есть массив объектов Javascript, как показано ниже

 const lab = [
  {
    name: "Lance",
    item: "PS",
    "3-Aug-21": "117.69",
    "4-Aug-21": "120.1",
    "5-Aug-21": "122.08",
  },
  {
    name: "Sam",
    item: "PS",
    "3-Aug-21": "100.14",
    "4-Aug-21": "101.2",
    "5-Aug-21": "103",
  },
  {
    name: "Vince",
    item: "PS",
    "3-Aug-21": "12.65",
    "4-Aug-21": "13.29",
    "5-Aug-21": "13.68",
  },
];
 

Я изменил это, как показано ниже

 const labCheck = [
  {
    id: "Lance",
    values: [
      { date: "3-Aug-21", risklevel: "117.69" },
      { date: "4-Aug-21", risklevel: "120.1" },
      { date: "5-Aug-21", risklevel: "122.08" },
    ],
  },
  {
    id: "Sam",
    values: [
      { date: "3-Aug-21", risklevel: "100.14" },
      { date: "4-Aug-21", risklevel: "101.2" },
      { date: "5-Aug-21", risklevel: "103" },
    ],
  },
  {
    id: "Vince",
    values: [
      { date: "3-Aug-21", risklevel: "12.65" },
      { date: "4-Aug-21", risklevel: "13.29" },
      { date: "5-Aug-21", risklevel: "13.68" },
    ],
  },
];
 

Я попробовал код ниже

 const labCheck = lab
  .map((d) => d.name)
  .map(function (name) {
    // console.log(id);
    return {
      id: name,
      values: Object.keys(lab[0])
        .slice(2)
        .map(function (d, id) {
          return {
            date: d,
            risklevel:  lab[id][d],
          };
        }),
    };
  });
 

Кажется, это работает, я понимаю структуру, но значения riskLevel одинаковы для всех id , и это неверно.

введите описание изображения здесь

Я пытался исправить это в течение нескольких дней, но безуспешно. Кто-нибудь может, пожалуйста, помочь?

Ответ №1:

Использование деструктурирования для выделения и переименования свойств, которые нас интересуют, на каждом уровне рефакторинга.

 const lab = [{ name: "Lance", item: "PS", "3-Aug-21": "117.69", "4-Aug-21": "120.1", "5-Aug-21": "122.08", }, { name: "Sam", item: "PS", "3-Aug-21": "100.14", "4-Aug-21": "101.2", "5-Aug-21": "103", }, { name: "Vince", item: "PS", "3-Aug-21": "12.65", "4-Aug-21": "13.29", "5-Aug-21": "13.68", },];

const labCheck = lab.map(({ name: id, item, ...values }) => ({
  id,
  values: Object.entries(values).map(([date, risklevel]) => ({ date, risklevel }))
}));

console.log(labCheck) 
 .as-console-wrapper { max-height: 100% !important; top: 0; } 

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

 const lab = [{ name: "Lance", item: "PS", "3-Aug-21": "117.69", "4-Aug-21": "120.1", "5-Aug-21": "122.08", }, { name: "Sam", item: "PS", "3-Aug-21": "100.14", "4-Aug-21": "101.2", "5-Aug-21": "103", }, { name: "Vince", item: "PS", "3-Aug-21": "12.65", "4-Aug-21": "13.29", "5-Aug-21": "13.68", },];

const labCheck = lab.map(({ name: id, item, ...values }) => ({
  id,
  values: Object.entries(values).map(([date, risklevel]) => ({ 
    date: new Date(Date.parse(date)), // Date.parse() is not reliable, but used as example here.
    risklevel:  risklevel 
  }))
}));

console.log(labCheck) 
 .as-console-wrapper { max-height: 100% !important; top: 0; } 

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

1. Сообщество Javascript — это так круто. Я получил 5 ответов в течение 10 минут! Спасибо. Я буду принимать ответ Ника с тех пор, как он был первым (я новичок в JS и не знаю, как оценивать код по другим параметрам). Также проголосуйте за свой ответ.

2. не беспокойтесь, хотя использование slice() в этом ответе является хрупким, поскольку порядок ключей не гарантируется. Также изучите назначение деструктуризации, поскольку оно может быть мощным и описательным инструментом.

3. обязательно проверю это.

4. Хорошее разрушение

5. @moys Это должен быть приемлемый ответ. Срез небезопасен

Ответ №2:

Проблема в том, что здесь:

 Object.keys(lab[0])
 

Вы ВСЕГДА берете первый элемент массива вместо итерации по ним.

Кроме того, вы объединяете два .map метода. Когда вы это сделаете, вторая карта получит в качестве входных данных результат предыдущего метода, в вашем случае имя, тем самым потеряв доступ к исходному элементу.

Вы можете использовать:

 const lab=[{name:"Lance",item:"PS","3-Aug-21":"117.69","4-Aug-21":"120.1","5-Aug-21":"122.08"},{name:"Sam",item:"PS","3-Aug-21":"100.14","4-Aug-21":"101.2","5-Aug-21":"103"},{name:"Vince",item:"PS","3-Aug-21":"12.65","4-Aug-21":"13.29","5-Aug-21":"13.68"}];


const labCheck = lab.map((item) => {
  return {
    id: item.name,
    values: Object.keys(item)
      // The order of the keys is not guaranteed, better not to use .slice() because it could fail on unpredicatable situations
      .filter((key) => key !== 'name' amp;amp; key !== 'item')
      .map((key) => {
        return { date: key, riskLevel: item[key] }
      })
  }
})

console.log(labCheck) 

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

1. Лучший ответ имо, должен быть принятым

Ответ №3:

Вы можете сделать что-то вроде этого :

 const lab = [
  {
    name: "Lance",
    item: "PS",
    "3-Aug-21": "117.69",
    "4-Aug-21": "120.1",
    "5-Aug-21": "122.08",
  },
  {
    name: "Sam",
    item: "PS",
    "3-Aug-21": "100.14",
    "4-Aug-21": "101.2",
    "5-Aug-21": "103",
  },
  {
    name: "Vince",
    item: "PS",
    "3-Aug-21": "12.65",
    "4-Aug-21": "13.29",
    "5-Aug-21": "13.68",
  },
];

const formattedLab = lab.map((el) => {
  const values = Object.entries(el).slice(2);
  return {
    id: el.name,
    values: values.map(value => ({
      date: value[0],
      riskLevel:  value[1]
    })),
  }
});

console.log(formattedLab); 

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

1. Большое вам спасибо! Я ломаю голову над этим уже 2 дня!

2. Обратите внимание на приведение к плаванию с использованием унарного плюса. Может быть, они вам нужны как струны?

3. Мне нужен на самом деле уровень риска в виде цифр, так что унарный плюс идеально подходит. Это плюс для этого ответа 🙂

Ответ №4:

map над Object.entries , чтобы получить доступ к данным в массиве и вернуть их.

 const lab=[{name:"Lance",item:"PS","3-Aug-21":"117.69","4-Aug-21":"120.1","5-Aug-21":"122.08"},{name:"Sam",item:"PS","3-Aug-21":"100.14","4-Aug-21":"101.2","5-Aug-21":"103"},{name:"Vince",item:"PS","3-Aug-21":"12.65","4-Aug-21":"13.29","5-Aug-21":"13.68"}];

// `map` over the array
const out = lab.map(obj => {

  // Grab the name, and item, and then everything else
  const { name, item, ...rest } = obj;

  // `map` over the object entries and for each iteration
  // return a new object
  const values = Object.entries(rest).map(([key, value]) => {
    return { date: key, riskLevel: value };
  });

  // Return the new array
  return { name, values };

});

console.log(out); 

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

1. Сообщество Javascript — это так круто. Я получил 5 ответов в течение 10 минут! Спасибо. Я буду принимать ответ Ника с тех пор, как он был первым (я новичок в JS и не знаю, как оценивать код по другим параметрам). Также проголосуйте за свой ответ.

Ответ №5:

Это работает для меня:

 const labCheck = lab.map((obj, i) => {
    const newObj = {id: obj.name, values: []};
    Object.keys(lab[i]).slice(2).forEach(date => {
        newObj.values.push({
            date: date, 
            risklevel: lab[i][date]
        });
    })
    return newObj;
})