简体   繁体   中英

JavaScript - Object from two array (parent and child elements)

I have 2 Arrays:

var links = [
  {
    code: 'home'
  },
  {
    code: 'contact'
  },
];

var subLinks = [
  {
    code: 'some subLink',
    parent: {
      code: 'home'
    }
  },
  {
    code: 'some subLink 2',
    parent: {
      code: 'home'
    }
  },
  {
    code: 'some subLink 3',
    parent: {
      code: 'contact'
    }
  }
];

I need to have Object (link as key with array of subLinks):

var menu = {
  home: ["some subLink", "some subLink 2"],
  contact: ["some subLink 3"]
};

At this moment I have this...

links.map(link => ({
    [link.code]: subLinks.map(subLink => (subLink.parent.code === link.code && subLink.code))
}))

I absolutely love array transformations using functional JS...

const menu = {};

links.map(link => menu[link.code] = subLinks
    .filter(sl => sl.parent.code === link.code)
    .map(sl => sl.code)
);

Using reduce...

const menu = links.reduce((memo, menu) => {
    memo[menu.code] = subLinks
        .filter(sl => sl.parent.code === menu.code)
        .map(sl => sl.code);
    return memo;
},{});

Both are pretty sweet, but reduce not having to create a variable to mutate inside the loops might just be a little sweeter.

 var links = [ { code: 'home' }, { code: 'contact' }, ]; var subLinks = [ { code: 'some subLink', parent: { code: 'home' } }, { code: 'some subLink 2', parent: { code: 'home' } }, { code: 'some subLink 3', parent: { code: 'contact' } } ]; var menu={}; for(var i=0;i<links.length;i++){ var code = links[i].code; menu[code]=[]; for(var j=0;j<subLinks.length;j++){ var subLink = subLinks[j]; if(subLink.parent && subLink.parent.code == code){ menu[code].push(subLink.code); } } } console.log(menu) 

You can do this in two passes: First, you iterate your links to create the base object with your parent links. Then, you iterate your subLinks to add them to the respective link that you added in the first pass.

This has the benefit that it explicitly only iterates each of your original arrays once .

 var links = [ { code: 'home' }, { code: 'contact' }, ]; var subLinks = [ { code: 'some subLink', parent: { code: 'home' } }, { code: 'some subLink 2', parent: { code: 'home' } }, { code: 'some subLink 3', parent: { code: 'contact' } } ]; // pass 1 var result = {}; for (var i = 0; i < links.length; i++) { result[links[i].code] = []; } // pass 2 for (var i = 0; i < subLinks.length; i++) { var subLink = subLinks[i]; result[subLink.parent.code].push(subLink.code); } console.log(result); 

Note that in your example, you do not explicitly need to have links . You can also construct the parent link on demand whenever you encounter a sub link with a parent that does not exist yet.

But having this separately allows you to expand your structure to include other information as well.

var x = subLinks.reduce((c, v) => {
    if(c.hasOwnProperty(v.parent.code)) c[v.parent.code].push(v.code);
    else c[v.parent.code] = [v.code];
    return c; 
}, {});

A double loop will do :

 var links = [ { code: 'home' }, { code: 'contact' }, ]; var subLinks = [ { code: 'some subLink', parent: { code: 'home' } }, { code: 'some subLink 2', parent: { code: 'home' } }, { code: 'some subLink 3', parent: { code: 'contact' } } ]; var menu = {}; for(var i=0;i<links.length;i++){ var prop = links[i].code; var child; menu[prop]=[]; for(var j=0;j<subLinks.length;j++){ var parent = subLinks[j].parent.code; if(parent==prop){ child = subLinks[j].code; menu[prop].push(child); } } } console.log(menu); 

Another solution:

 var links = [{ code: 'home' }, { code: 'contact' }]; var subLinks = [{ code: 'some subLink', parent: { code: 'home' } }, { code: 'some subLink 2', parent: { code: 'home' } }, { code: 'some subLink 3', parent: { code: 'contact' } }]; const result = links.reduce((o, x) => { o[x.code] = subLinks.filter(f => f.parent.code == x.code).map(m => m.code); return o; }, {}); console.log(result); 

Documentations:

/** you can also use something like this: 
here salesInvoice(parent) can have multiple salesInvoiceItems(child) **/

const salesInvoices = [{
        id: 1,
        invoice_no: 'inv1'
    },
    {
        id: 2,
        invoice_no: 'inv2'
    },
    {
        id: 3,
        invoice_no: 'inv3'
    },
    {
        id: 4,
        invoice_no: 'inv4'
    },
]

const salesInvoiceItems = [{
        id: 1,
        sales_invoice_id: 1,
        name: 'inv1item'
    },
    {
        id: 2,
        sales_invoice_id: 1,
        name: 'inv1item'
    },
    {
        id: 3,
        sales_invoice_id: 2,
        name: 'inv2item'
    },
    {
        id: 4,
        sales_invoice_id: 2,
        name: 'inv2item'
    },
    {
        id: 5,
        sales_invoice_id: 2,
        name: 'inv2item'
    },
    {
        id: 6,
        sales_invoice_id: 2,
        name: 'inv2item'
    },
    {
        id: 7,
        sales_invoice_id: 2,
        name: 'inv2item'
    },
    {
        id: 8,
        sales_invoice_id: 3,
        name: 'inv3item'
    },
    {
        id: 9,
        sales_invoice_id: 3,
        name: 'inv3item'
    },
    {
        id: 10,
        sales_invoice_id: 3,
        name: 'inv3item'
    },
    {
        id: 11,
        sales_invoice_id: 3,
        name: 'inv3item'
    },
    {
        id: 12,
        sales_invoice_id: 3,
        name: 'inv3item'
    },
    {
        id: 13,
        sales_invoice_id: 4,
        name: 'inv4item'
    },
    {
        id: 14,
        sales_invoice_id: 4,
        name: 'inv4item'
    },
    {
        id: 15,
        sales_invoice_id: 4,
        name: 'inv4item'
    },
]


for (let singleItem of salesInvoices) {
    const InvoiceItems = salesInvoiceItems.filter(item => item.sales_invoice_id == singleItem.id);
    singleItem.salesInvoiceItemList = InvoiceItems;
}

console.log(salesInvoices)

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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