1

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))
}))
1
  • 2
    map will return an array. Consider using reduce. Commented Oct 25, 2017 at 11:17

7 Answers 7

3

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.

Sign up to request clarification or add additional context in comments.

4 Comments

Note that this fully iterates subLinks exactly links.length times.
There wasnt any spec of O notation ;)
It wasn’t meant as criticism, just a friendly note ;) I still like your code! :D
Not taken as criticism! :) I find most readable code is usually the best - deal with any O stuff as it comes. Sometime arrays are just smallish and it wont matter we are making more iterations than actually required.
1
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; 
}, {});

Comments

1

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.

Comments

1

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)

1 Comment

Note that this fully iterates subLinks exactly links.length times.
0

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:

Comments

0

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);

1 Comment

Thanks Werner, it's better that way
0
/** 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)

1 Comment

As it’s currently written, your answer is unclear. Please edit to add additional details that will help others understand how this addresses the question asked. You can find more information on how to write good answers in the help center.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.