简体   繁体   English

使用递归解析 Javascript 中的嵌套对象数组

[英]Parsing an array of nested objects in Javascript using recursion

I want to print all the brand names with their parent name by traversing through this array.我想通过遍历这个数组来打印所有品牌名称及其父名称。 For top level brands, parent as "None".对于顶级品牌,父级为“无”。
eg None: Parle, Parle: Parle Agro, Parle Agro: Frooti例如None: Parle, Parle: Parle Agro, Parle Agro: Frooti

let inventory = [
  {
    brand: 'Parle',
    products: [
      {
        brand: 'Parle Agro',
        products: [
          {
            brand: 'Frooti',
            products: []
          },
          {
            brand: 'Bailey',
            products: []
          }
        ]
      }
    ]
  },
  {
    brand: 'Pepsico',
    products: [
      {
        brand: 'VB',
        products: [
          {
            brand: 'Lays',
            products: []
          },
          {
            brand: 'Kurkure',
            products: [
              {
                brand: 'Mad Angles',
                products: []
              }
            ]
          }
        ]
      },
      {
        brand: 'Pepsi',
        products: []
      }
    ]
  },
  {
    brand: 'Cadbury',
    products: []
  } 
];

I have tried following approach but I'm missing out somewhere.我尝试了以下方法,但我错过了某个地方。

function brandName(obj){
for (var key in obj) {
    var item = obj[key];
    if (typeof item === "object"){
        brandName(item.products); }
} } brandName(inventory);

Basically I've used a recursion that gets an inventory and a parent (default None) and prints the parent along with all the children.基本上我使用了一个递归,它获取一个库存和一个父级(默认为无)并打印父级和所有子级。 Then doing recursion for each of the children, having the child itself as parent.然后为每个孩子做递归,让孩子自己作为父母。 It's easier to see the code.更容易看到代码。

 var inventory = [{brand:"Parle",products:[{brand:"Parle Agro",products:[{brand:"Frooti",products:[]},{brand:"Bailey",products:[]}]}]},{brand:"Pepsico",products:[{brand:"VB",products:[{brand:"Lays",products:[]},{brand:"Kurkure",products:[{brand:"Mad Angles",products:[]}]}]},{brand:"Pepsi",products:[]}]},{brand:"Cadbury",products:[]}] function brandName(inventory, parent) { parent = parent || "None" inventory.forEach(function(item) { console.log(parent + ": " + item.brand) brandName(item.products, item.brand) }) } brandName(inventory);
 .as-console-wrapper { max-height: 100%;important; }

Here's a recursive generator that allows the caller to decide the effect.这是一个递归生成器,允许调用者决定效果。 menu does a simple type analysis on the input t and responds accordingly - menu对输入t进行简单的类型分析并做出相应的响应 -

 function *menu(t, parent = "None") { switch (t?.constructor) { case Array: for (const child of t) yield *menu(child, parent) break case Object: yield [parent, t.brand] yield *menu(t.products, t.brand) break } } const inventory = [{brand:"Parle",products:[{brand:"Parle Agro",products:[{brand:"Frooti",products:[]},{brand:"Bailey",products:[]}]}]},{brand:"Pepsico",products:[{brand:"VB",products:[{brand:"Lays",products:[]},{brand:"Kurkure",products:[{brand:"Mad Angles",products:[]}]}]},{brand:"Pepsi",products:[]}]},{brand:"Cadbury",products:[]}] for (const item of menu(inventory)) console.log(item.join(":"))
 .as-console-wrapper { min-height: 100%; top: 0; }

None:Parle
Parle:Parle Agro
Parle Agro:Frooti
Parle Agro:Bailey
None:Pepsico
Pepsico:VB
VB:Lays
VB:Kurkure
Kurkure:Mad Angles
Pepsico:Pepsi
None:Cadbury

If you want to collect all of the items in an array, use Array.from -如果要收集数组中的所有项目,请使用Array.from -

Array.from(menu(inventory))
// => [ ["None", "Parle"], ["Parle", "Parle Agro"], ...]
Array.from(menu(inventory), p => p.join(":"))
// [ "None:Pare", "Parle:Parle Agro", ...]

A simple recursion will extract all the brand/parent pairs into an array of objects:一个简单的递归会将所有品牌/父母对提取到一个对象数组中:

 const collectBrands = (xs, parent = "None") => xs.flatMap (({brand, products = []}) => [ {brand, parent}, ... collectBrands (products, brand) ]) const inventory = [{brand: "Parle", products: [{brand: "Parle Agro", products: [{brand: "Frooti", products: []}, {brand: "Bailey", products: []}]}]}, {brand: "Pepsico", products: [{brand: "VB", products: [{brand: "Lays", products: []}, {brand: "Kurkure", products: [{brand: "Mad Angles", products: []}]}]}, {brand: "Pepsi", products: []}]}, {brand: "Cadbury", products: []}] console.log (collectBrands (inventory))
 .as-console-wrapper {max-height: 100%;important: top: 0}

We simply map over the input, extracting the current brand and parent into an object (defaulting parent to 'None' ), recurring on the list of products , and combining them into a single list.我们在输入上简单地map ,将当前brandparent级提取到 object(默认parent级为'None' ),在products列表中重复出现,并将它们组合成一个列表。 By using flatMap we combined these into a single list of results.通过使用flatMap ,我们将这些组合成一个结果列表。

That will yield something like this:这将产生如下内容:

[
  {brand: "Parle", parent: "None"},
  {brand: "Parle Agro", parent: "Parle"}, 
  {brand: "Frooti", parent: "Parle Agro"}, 
  {brand: "Bailey", parent: "Parle Agro"},
  {brand: "Pepsico", parent: "None"},
  {brand: "VB", parent: "Pepsico"},
  {brand: "Lays", parent: "VB"},
  {brand: "Kurkure", parent: "VB"},
  {brand: "Mad Angles", parent: "Kurkure"},
  {brand: "Pepsi", parent: "Pepsico"},
  {brand: "Cadbury", parent: "None"}
]

And if you want them all in your String format, you can create this array and then format it with something like this: :如果您希望它们全部采用 String 格式,您可以创建此数组,然后使用以下格式对其进行格式化:

console .log (
  collectBrands (inventory) .map (({parent, brand}) => `${parent}: ${brand}`) .join (', ')
) 
//=> "None: Parle, Parle: Parle Agro, Parle Agro: Frooti, Parle Agro: Bailey, None: Pepsico, Pepsico: VB, VB: Lays, VB: Kurkure, Kurkure: Mad Angles, Pepsico: Pepsi, None: Cadbury"

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

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