Объединить объект в массив с javascript - PullRequest
0 голосов
/ 29 января 2020

У меня есть три объекта (productData, stockData, locationData). У productData есть два данных productId и productName. У stockData есть productId, locationId и запас. Я хочу объединить все это в новый массив. Например, у меня есть три объекта, таких как приведенный ниже фрагмент кода, затем объедините его:

const productData = [
  {productId: 1000,productName: 'Product 1000'},
  {productId: 1001,productName: 'Product 1001'}
];
const stockData = [
  {productId: 1000,locationId: 1,stock: 21},
  {productId: 1000,locationId: 2,stock: 8},
  {productId: 1001,locationId: 1,stock: 4},
  {productId: 1001,locationId: 2,stock: 10}
];
const locationData = [
  {locationId: 1,locationName: 'Location 1'},
  {locationId: 2,locationName: 'Location 2'}
];

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

const result = [
  {
    productName: 'Product 1000',
    stock: {
      total: 29,
      detail: [
        {
          locationName: 'Location 1',
          stock: 21
        },
        {
          locationName: 'Location 2',
          stock: 8
        }
      ]
    }
  },
  {
    productName: 'Product 1001',
    stock: {
      total: 14,
      detail: [
        {
          locationName: 'Location 1',
          stock: 4
        },
        {
          locationName: 'Location 2',
          stock: 10
        }
      ]
    }
  }
];

У меня нет идея, пока я делаю так:

function mergeArrayObjects(arr1,arr2,arr3){

  let mulai = 0;
  let stok = 0;
  let stok2 = 0;
  let mulaiStok = 0;
  let detail = [];
  let merge = [];

  while(mulai < arr1.length){
        while(mulaiStok < arr2.length){
            if(arr1[0].productId === arr2[mulaiStok].productId){
                stok = stok + arr2[mulaiStok].stock
            }
            if(arr1[1].productId === arr2[mulaiStok].productId){
                stok2 = stok2 + arr2[mulaiStok].stock
            }
            mulaiStok++
        }

        merge.push({
          productName: arr1[mulai].productName,
          stock: {
            total:stok2,
            detail:detail}
        })
        mulai++
  }
  return merge;
}
console.log(mergeArrayObjects(productData, stockData, locationData))

Ответы [ 4 ]

1 голос
/ 29 января 2020

Я бы начал с итерации списка productData и создания пустого объекта продукта для каждого из них, такого как:

       let product = {
            productName: pd.productName,
            stock: {
                total: 0,
                detail: []
            }
        };

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

Вы также можете начать с итерации по списку stockData, если хотите.

Это должно сделать работу:

const productData = [
  {productId: 1000,productName: 'Product 1000'},
  {productId: 1001,productName: 'Product 1001'}
];
const stockData = [
  {productId: 1000,locationId: 1,stock: 21},
  {productId: 1000,locationId: 2,stock: 8},
  {productId: 1001,locationId: 1,stock: 4},
  {productId: 1001,locationId: 2,stock: 10}
];
const locationData = [
  {locationId: 1,locationName: 'Location 1'},
  {locationId: 2,locationName: 'Location 2'}
];



function mergeObj(productDataList, stockDataList, locationDataList) {
    let result = [];
    productDataList.forEach(pd => {
        let product = {
            productName: pd.productName,
            stock: {
                total: 0,
                detail: []
            }
        };
        let stockList = stockDataList.filter(sd => sd.productId === pd.productId);
        if (stockList.length > 0) {
            stockList.forEach(sl => {
                let location = locationDataList.find(ld => ld.locationId === sl.locationId);
                if (location) {
                    let detail = {
                        locationName: location.locationName,
                        stock: sl.stock
                    }
                    product.stock.total += sl.stock;
                    product.stock.detail.push(detail);
                } else {
                    console.error('Location not found for stock data');
                }

            })
        }

        result.push(product);
    });
    return result;
}

console.log('Object merged: ', mergeObj(productData, stockData, locationData));
0 голосов
/ 30 января 2020

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

const combineStock = (productData, stockData, locationData) => {
  const products = productData .reduce ((a, {productId, productName}) => ({...a, [productId]: productName}), {})
  const locations = locationData .reduce ((a, {locationId, locationName}) => ({...a, [locationId]: locationName}), {})

  const collectStock = (stockLocations) => stockLocations .reduce ( 
    ({total, details}, {locationId, stock}) => ({
      total: total + stock,
      details: [... details, {locationName: locations [locationId], stock}]
    }),
    {total: 0, details: []}
  )
  
  return  Object.entries (
    Object .entries (
      stockData .reduce ((a, {productId, ... rest}) => ({... a, [productId]: [... (a [productId] || []), rest]}), {})
    ) 
    .reduce ((a, [k, v]) => ({... a, [k]: collectStock (v)}), {})
  )
  .map (([productId, stock]) => ({
    productName: products [productId],
    stock
  })) 
}

const productData = [{productId: 1000, productName: 'Product 1000'}, {productId: 1001, productName: 'Product 1001'}]
const stockData = [{productId: 1000, locationId: 1, stock: 21}, {productId: 1000, locationId: 2, stock: 8}, {productId: 1001, locationId: 1, stock: 4}, {productId: 1001, locationId: 2, stock: 10}]
const locationData = [{locationId: 1, locationName: 'Location 1'}, {locationId: 2, locationName: 'Location 2'}]

console .log (combineStock (productData, stockData, locationData))

Это происходит в несколько этапов.

Первая строка превращает productData в нечто подобное:

{1000:"Product 1000", 1001: "Product 1001"}

и следующий делает нечто подобное для locationData. Это просто облегчает поиск их имен по идентификаторам.

Мы определяем collectStock помощник, который преобразует массив следующим образом:

[{locationId: 1, stock: 21}, {locationId: 2, stock: 8}]

в это:

{
  total: 29,
  details: [{locationName: "Location 1", stock: 21}, {locationName: "Location 2", stock: 8}]
}

с использованием поиска locations.

Остальная часть является основной функцией. Строка stockData .reduce (...) создает такую ​​структуру:

{
  "1000": [{"locationId": 1, "stock": 21}, {"locationId": 2, "stock": 8}], 
  "1001": [{"locationId": 1, "stock": 4}, {"locationId": 2, "stock": 10}]
}

После того, как мы обернули это Object.entries и вызвали reduce для него с вызовом collectStock, мы получили что-то вроде этого:

{
  1000: {
    total: 29,
    details: [{locationName: "Location 1", stock: 21}, {locationName: "Location 2", stock: 8}]
  }, 
  1001: {
    total: 14,
    details: [{locationName: "Location 1", stock: 4}, {locationName: "Location 2", stock: 10}] 
  }
}

Затем мы вызываем Object.entries для этого результата и map полученные пары в наш окончательный формат, используя поиск products.

0 голосов
/ 29 января 2020

Вы можете воспользоваться Map и собрать на первом этапе некоторые связанные данные с помощью ключа. Позже примите эти значения для более быстрого доступа без повторения итераций массивов.

Вам нужны карты для locations, products и details продукта и местоположения, которые в начале пусты.

Из карты products получите значения как набор результатов.

Наконец, выполните итерацию stockData один раз и получите продукт и детали, а detail не существует для данного продукта и местоположения, создайте новый объект и вставьте это в карту данных и вставьте sh в свойство продукта.

При последнем обновлении stock из detail и total из product.

const
    // main data
    productData = [{ productId: 1000, productName: 'Product 1000' }, { productId: 1001, productName: 'Product 1001' }],
    stockData = [{ productId: 1000, locationId: 1, stock: 21 }, { productId: 1000, locationId: 2, stock: 8 }, { productId: 1001, locationId: 1, stock: 4 }, { productId: 1001, locationId: 2, stock: 10 }],
    locationData = [{ locationId: 1, locationName: 'Location 1' }, { locationId: 2, locationName: 'Location 2' }],

    // maps as helpers
    locations = new Map(locationData.map(({ locationId, locationName }) => [locationId, locationName])),
    products = new Map(productData.map(({ productId, productName }) => [productId, { productName, stock: { total: 0, detail: [] } }])),
    details = new Map,

    // literally the result
    result = Array.from(products.values());

stockData.forEach(({ productId, locationId, stock }) => {
    var product = products.get(productId),
        detailKey = `${productId}|${locationId}`,
        detail = details.get(detailKey);

    if (!detail) {
        detail = { locationName: locations.get(locationId), stock: 0 };
        details.set(detailKey, detail);
        product.stock.detail.push(detail);
    }

    detail.stock += stock;
    product.stock.total += stock;
});

console.log(result);
.as-console-wrapper { max-height: 100% !important; top: 0; }
0 голосов
/ 29 января 2020

Вы можете сгруппировать данные stock и location, затем сопоставить данные product следующим образом

const productData = [
  { productId: 1000, productName: 'Product 1000' },
  { productId: 1001, productName: 'Product 1001' }
];
const stockData = [
  { productId: 1000, locationId: 1, stock: 21 },
  { productId: 1000, locationId: 2, stock: 8 },
  { productId: 1001, locationId: 1, stock: 4 },
  { productId: 1001, locationId: 2, stock: 10 }
];
const locationData = [
  { locationId: 1, locationName: 'Location 1' },
  { locationId: 2, locationName: 'Location 2' }
];

function group(arr, by) {
  return arr.reduce((acc, curr) => {
    let key = curr[by];
    delete curr[by];
    acc.set(key, [...acc.get(key) || [], curr]);
    return acc;
  }, new Map())
}

let groupedstockData = group(stockData, 'productId');
let groupedLocationData = group(locationData, 'locationId');

let out = productData.map(({ productName, productId }) => {
  let stockdata = groupedstockData.get(productId);
  let sum = 0;
  return {
    productName, stock: {
      detail: stockdata.map(({ locationId, stock }) => {
        let [{ locationName }] = groupedLocationData.get(locationId);
        sum += stock;
        return { locationName, stock }
      }), total: sum
    }
  }
});
console.log(out)
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...