JavaScript: Преобразование и структурирование массива строк в массив объектов

#javascript #arrays

Вопрос:

У меня есть массив строк, который является результатом сканирования штрих-кодов. В настоящее время это выглядит так:

 var array = ['NEW', '1111', 'serial1', 'serial2, 'NEW', '2222', 'serial3', 'serial4']; 
 

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

 var objects = [
                {
                  order_id: '1111',
                  serial_numbers: ['serial1', 'serial2']
                },
                {
                  order_id: '2222',
                  serial_numbers: ['serial3', 'serial4']
                }
]
 

Как вы можете видеть, ключевое слово «НОВЫЙ» всегда указывает, что order_id следующим будет an (например, «1111»). После order_id того, как несколько serial_numbers будут следовать до следующей «НОВОЙ» записи.

Я попытался структурировать массив с помощью индексов, но это не сработало.

Заранее благодарю вас!

Ответ №1:

Вы можете легко достичь этого результата, используя reduce

 var array = [
  "NEW",
  "1111",
  "serial1",
  "serial2",
  "NEW",
  "2222",
  "serial3",
  "serial4",
];

const result = array.reduce((acc, curr) => {
  if (curr === "NEW") acc.push({ order_id: "", serial_numbers: [] });
  else {
    const last = acc[acc.length - 1];
    if (!last.order_id) last.order_id = curr;
    else last.serial_numbers.push(curr);
  }

  return acc;
}, []);

console.log(result); 
 /* This is not a part of answer. It is just to give the output fill height. So IGNORE IT */
.as-console-wrapper { max-height: 100% !important; top: 0; } 

Ответ №2:

Привет, чувак, я бы сделал это следующим образом, если бы было фиксированное количество серийных номеров:

 function parseArray(input) {
  let output = [];
  for (let i = 0; i < array.length; i  ) {
    if (array[i] === 'NEW') {
      output.push({
        order_id: array[i   1],
        serial: [array[i   2], array[i   3]]
      });
      i  = 3;
    }
  }
  return output;
}
 

Вы можете посмотреть мой stackblitz для бегущего примера: https://stackblitz.com/edit/web-platform-ec4kcw?file=script.js

Редактировать:

я изменил функцию, чтобы теперь также размещать сериалы любой длины:

 function parseArray(input) {
  let output = [];
  let item = {};
  for (let i = 0; i < input.length; i  ) {
    if (input[i] === 'NEW') {
      item = {
        order_id: input[i   1],
        serial: []
      };
      output.push(item);
      i  = 1;
    } else {
      item.serial.push(input[i]);
    }
  }
  return output;
}
 

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

1. Спасибо за ваш ответ. Количество серийных номеров, к сожалению, не фиксировано.

Ответ №3:

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

 var array = ['NEW', '1111', 'serial1', 'serial2', 'NEW', '2222', 'serial3', 'serial4'];

// Create an array of array consisting of the serial numbers
// The first item of the array is the order id
function parseOrders(items) {
  const orders = [];
  let orderItems = [];
  
  items.forEach((item) => {
    if (item === 'NEW') {
      if (orderItems.length > 0) {
        orders.push(orderItems);
      }
      orderItems = [];
    } else {
      orderItems.push(item)
    }
  })

  if (orderItems.length > 0) orders.push(orderItems);
  return orders;
}

function transformToObjects(orders) {
  const objects = [];
  orders.forEach((order) => {
    const orderId = order[0];
    const serialNumbers = order.slice(1);
    objects.push({
      order_id: orderId,
      serial_numbers: serialNumbers,
    })
  })
  return objects;
}

const orders = parseOrders(array);
const objects = transformToObjects(orders);
console.log(objects);
 

Ответ №4:

 const output = array.reduce((prev,curr,index,arr)=>{
if(curr==='NEW') {
    return prev.concat({
        order_id: arr[index 1],
        serial_numbers: [arr[index 2], arr[index 3]]
    });
}
return prev;
},[]); 
 

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