简体   繁体   English

减少、展平和转换嵌套数组

[英]Reduce, flatten and transform nested array

I am trying to find a solution to get a specific format for my nested JSON array.我试图找到一种解决方案来为我的嵌套 JSON 数组获取特定格式。 I have tried to use Lodash groupBy and Javascript reduce but I can not seem to find a solution.我曾尝试使用Lodash groupByJavascript reduce,但似乎找不到解决方案。

Input format:输入格式:

[
  { 
     lineitem: {
        id:1,
        price: { 
            amount:100
        },
        supplierName:TestSupplier1
     },
     quantity:10
  }, 
  {
     lineitem: {
        id:2,
        price: { 
            amount:200
        },
        supplierName:TestSupplier2
    },
    quantity:20
  },
  { 
     lineitem: {
        id:3,
        price: { 
            amount:300
        },
        supplierName:TestSupplier1
     },
     quantity:30
  }, 
  {
     lineitem: {
        id:4,
        price: { 
            amount:400
        },
        supplierName:TestSupplier4
    },
    quantity:40
  },
]

Desired output format:所需的输出格式:

[
  { 
     TestSupplier1: [
        {
           id:1,               
           amount:100,
           quantity:10
        },
        {
           id:3,
           amount:300,              
           quantity:30            
        }
     ],
     TestSupplier2: [
        {
           id:2,
           amount:200,               
           quantity:20    
        }
     ],
     TestSupplier4: [
        {
          id:4,              
          amount:400,
          quantity:40
        }
     ]
]

As I see it there are 3 steps here:在我看来,这里有 3 个步骤:

  1. Group by supplierName供应商名称分组
  2. Flatten the price object压平价格对象
  3. Move quantity into lineitem数量移动到lineitem

Can anyone help solve this?任何人都可以帮助解决这个问题吗?

Update 1更新 1

After succesfully grouped by supplierName I now want to flatten the array further.在按供应商名称成功分组后,我现在想进一步展平阵列。 Such that the TestSupplier'X' is placed within each array.这样 TestSupplier'X' 被放置在每个阵列中。

See example below:请参阅下面的示例:

[
    {
       supplierName:TestSupplier1,
       id:1,               
       amount:100,
       quantity:10
    },
    {   
       supplierName:TestSupplier1,
       id:3,
       amount:300,              
       quantity:30            
    },
    {
       supplierName:TestSupplier2,
       id:2,
       amount:200,               
       quantity:20    
    },
    {
       supplierName:TestSupplier4,
       id:4,              
       amount:400,
       quantity:40
    }
]

This should get you pretty much what you want, the only thing to note is that you can't have an object with multiple keys that are the same, so you have an array of objects rather than having an object with several keys of lineItem :这应该可以满足您的需求,唯一需要注意的是,您不能拥有一个具有多个相同键的对象,因此您拥有一个对象数组,而不是拥有一个具有多个lineItem键的lineItem

const result = data.reduce((result, item) => {
  // Get the supplier name, id, amount and quantity of the current item
  const supplierName = item.lineitem.supplierName;

  const {
    id,
    price: { amount }
  } = item.lineitem;
  const { quantity } = item;

  const lineItem = {
    id,
    amount,
    quantity
  };

  // If it already exists in the result, add the data to the existing key
  if (Object.keys(result).includes(supplierName)) {
    return Object.assign({}, result, {
      [supplierName]: [...result[supplierName], lineItem]
    });
  } else {
    // Otherwise create a new key
    return Object.assign({}, result, { [supplierName]: [lineItem] });
  }
}, {});

This gives you:这给你:

{ TestSupplier1:
   [ { id: 1, amount: 100, quantity: 10 },
     { id: 3, amount: 300, quantity: 30 } ],
  TestSupplier2: [ { id: 2, amount: 200, quantity: 20 } ],
  TestSupplier4: [ { id: 4, amount: 400, quantity: 40 } ] }

In the original question you asked for the whole thing to be wrapped in an array, which is obviously as simple as [result] .在最初的问题中,您要求将整个事物包装在一个数组中,这显然与[result]一样简单。

let resObj = {};
data.forEach( el => {
    if(!Object.keys(resObj).includes(el.lineitem.supplierName))
    {
        console.log(el);
        resObj[el.lineitem.supplierName] = [];
        }
    let newInnerObj = { id: el.lineitem.id, amount: el.lineitem.price.amount, quantity: el.quantity };
    resObj[el.lineitem.supplierName].push(newInnerObj);
});

console.log(resObj);

Here is a simple answer, but like I said in my comment- you can't have object with properties of the same name, so the result is an object with TestSupplierX as properties, and each property si an array of object with the structure you requested.这是一个简单的答案,但就像我在评论中所说的那样-您不能拥有具有相同名称属性的对象,因此结果是具有TestSupplierX作为属性的对象,并且每个属性都是一个具有您的结构的对象数组要求。

It is really as simple as moving through all the original array and just construct the right object.它真的就像遍历所有原始数组并构造正确的对象一样简单。 What I think you missed is how to get them into the correct property name which comes from supplierName, and this is done just by checking if the result object already has it with Object.keys(obj).includes(key) , and if it doesn't- create it simply by accessing it and initializing it to an empty array.我认为你错过的是如何让它们进入来自供应商名称的正确属性名称,这只是通过检查结果对象是否已经具有Object.keys(obj).includes(key) ,如果它不会 - 简单地通过访问它并将其初始化为空数组来创建它。

If you're working in TypeScript, the following might help:如果您正在使用 TypeScript,以下内容可能会有所帮助:

interface IInput {
  lineitem: {
    id: number;
    price: {
      amount: number;
    }
    supplierName: string;
  }
  quantity: number;
}

interface IOutputA {
  [key: string]: {
    id: number;
    amount: number;
    quantity: number;
  }[];
}

interface IOutputB {
  supplierName: string;
  id: number;
  amount: number;
  quantity: number;
}

function transformA(input: IInput[]): IOutputA {
  const ret: IOutputA = {};
  input.forEach(it => {
    ret[it.lineitem.supplierName] = [];
    ret[it.lineitem.supplierName].push({
      id: it.lineitem.id,
      amount: it.lineitem.price.amount,
      quantity: it.quantity,
    }
  }
  return ret;
}

function transformB(outputA: IOutputA): IOutputB {
  const ret: IOutputB = [];
  Object.keys(outputA).forEach(x => {
    outputA[x].forEach(y => {
      ret.push({
        supplierName: x,
        id: y.id,
        amount: y.amount,
        quantity: y.quantity,
      });
    });
  });
  return ret;
}

It would be nice to see your attempt at solving this as well.很高兴看到您也尝试解决这个问题。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM