Use object property values of two JS array of objects - javascript

I have two arrays
let arr1 = [{'id': 'ee', 'seat': '12'},
{'id': 'aa', 'seat': '8'}
]
let arr2 = [
{'id': 's22', 'num': ''},
{'id': '2s2', 'num': ''}
]
I want to copy seat values from arr1 to num property at arr2, but I only get last arr1 seat value in for loop.
for( let i = 0; i <= arr1.length; i++) {
for( let x = 0; x <= arr2.length; x++) {
arr2[x]['num'] = arr1[i]['seat'];
}
}
console.log(arr2);

Iterate arr2 with Array.forEach(), and take the respective seat value by index from arr1:
const arr1 = [{'id': 'ee', 'seat': '12'},{'id': 'aa', 'seat': '8'}]
const arr2 = [{'id': 's22', 'num': ''},{'id': '2s2', 'num': ''}]
arr2.forEach((o, i) => o.num = arr1[i].seat)
console.log(arr2)

You need just a single loop and check if the index of the array if is (only) smaller than the length of the minimum of both arrays.
If the index get the length of an array, the access returns undefined, because this element is not in the array.
A further access to a property of this throws an error:
Unable to get property 'seat' of undefined or null reference
var arr1 = [{ id: 'ee', seat: '12' }, { id: 'aa', seat: '8' }],
arr2 = [{ id: 's22', num: '' }, { id: '2s2', num: '' }],
i, l;
for (i = 0, l = Math.min(arr1.length, arr2.length); i < l; i++) {
arr2[i].num = arr1[i].seat;
}
console.log(arr2);

You can do it in just one for loop.
for(let i = 0; i < arr1.length; i++) {
arr2[i].num = arr1[i].seat;
}
Hope this helps!

Assuming you want to match indices, this should do it.
const arr1 = [
{'id': 'ee', 'seat': '12'},
{'id': 'aa', 'seat': '8'}
]
const arr2 = [
{'id': 's22', 'num': ''},
{'id': '2s2', 'num': ''}
]
const result = arr2.map((e, i) => ({...e, ...{num: arr1[i].seat}}))
console.log(result)
If you want all of the seats in each num, it wouldn't be much harder.

Related

lodash - filter collection by nested items count

Is there any simple solution (vanilla js or lodash) to filter collection by nested items count?
For example there is following grouped collection:
[
{
Items: ['a', 'b', 'c'],
Name: 'Group 1'
},
{
Items: ['d', 'e','f'],
Name: 'Group 2'
}
]
If I need to take 2 items it should return:
[
{
Items: ['a', 'b'],
Name: 'Group 1'
}
]
If I need to take 5 items it should return:
[
{
Items: ['a', 'b', 'c'],
Name: 'Group 1'
},
{
Items: ['d', 'e'],
Name: 'Group 2'
}
]
You need to iterate the items (for...of in this case), and count the number of items in the result + the current object items length.
If it's less or equal to the total wanted (n) you push the original object. If it's more, you slice the nested array, so it will include the difference.
If the current count is equal or more than n (or if the loop ends) return the result (res).
const fn = (arr, n, key) => {
let count = 0
const res = []
for(const o of arr) {
const len = o[key].length
res.push(count + len <= n ? o : { ...o, [key]: o[key].slice(0, n - count) })
count += len
if(count >= n) return res
}
return res
}
const arr = [{"Items":["a","b","c"],"Name":"Group 1"},{"Items":["d","e","f"],"Name":"Group 2"}]
console.log(fn(arr, 2, 'Items'))
console.log(fn(arr, 5, 'Items'))
console.log(fn(arr, 8, 'Items'))
My solution, maybe not perfect but it works :)
let array = [
{
Items: [
'a',
'b',
'c'
],
Name: 'Test1'
},
{
Items: [
'd',
'e',
'f'
],
Name: 'Test2'
}
];
let itemsCount = 5;
let filteredArray = [];
array.some(group => {
if (itemsCount <= 0) {
return true;
}
if (group.Items.length <= itemsCount) {
itemsCount -= group.Items.length;
} else {
group.Items = group.Items.slice(0, itemsCount);
itemsCount = 0;
}
filteredArray.push(group);
});
console.log(filteredArray);

Add Property to Object Array From Other Array - JS

I want to add a property to an array of objects from another existing array (both from the same length)
Example:
var array1 = [1, 2, 3];
var array2 = [{word: "hey"}, {word: "hello"}, {word: "world"}]
//Wanted Outcome: array2 = [{word: "hey", id: 1}, {word: "hello", id: 2}, {word: "world", id: 3}]
What I've tried:
for(var i=0; i<array1.length; i++){
for(var j= 0; j<array2.length; j++){
array2[j].id = array1[i];
}
}
//Outcome Im getting: array2 = [{word: "hey", id: 3}, {word: "hello", id: 3}, {word: "world", id: 3}]
How can I add a different property based on the first array length to the second array?
This is what you need
array2.forEach((item, i) => {
item.id = array1[i]
})
You don't need a nested loop here. Just you one level for loop and use i as both the indices
var array1 = [1, 2, 3];
var array2 = [{word: "hey"}, {word: "hello"}, {word: "world"}]
for(let i = 0; i < array2.length; i++){
array2[i].id = array1[i];
}
console.log(array2);
Cleaner way for doing this is to use map()
var array1 = [1, 2, 3];
var array2 = [{word: "hey"}, {word: "hello"}, {word: "world"}]
array2 = array2.map((x, i) => ({...x, id: array1[i]}));
console.log(array2);

Javascript merge the values of 4 arrays into one object

I have 4 arrays of the following format
arr1 = ['Hello', 'World', 'Hi']
arr2 = ['1', '2', '3']
arr3 = ['foo', 'bar', 'foobar']
arr4 = ['10', '20', '30']
I am trying to add each value at index[i] to a new object, the object looks like this
obj = {
title: '',
score: '',
description: '',
value: '',
}
For each indexed value in the array I would like to push it to a new instance of the obj object so I can end up with this
objects = [
{
title: 'Hello',
score: '1',
description: 'foo',
value: '10',
},
{
title: 'World',
score: '2',
description: 'bar',
value: '20',
},
{
title: 'Hi',
score: '3',
description: 'foobar',
value: '30',
}
]
So far I have been trying something like
objects = []
arr1.forEach((key, i) => objects[key] = arr2[i])
But that is assigning them as arr1val : arr2val
I will ultimately be setting this to state in my react app and passing it to another component as props to render on the page. The data is coming in from 3 different APIs, I am doing this to try and standardise the data received from each API so my component can use the data to render an articles list and user can switch between feeds.
Map by the index of element across all arrays, also use map not forEach:
const objects = arr1.map((element, index) => (
{title: element, score: arr2[index], description: arr3[index], value: arr4[index]}
))
Live demo is below:
const arr1 = ['Hello', 'World', 'Hi']
const arr2 = ['1', '2', '3']
const arr3 = ['foo', 'bar', 'foobar']
const arr4 = ['10', '20', '30']
const objects = arr1.map((element, index) => (
{title: element, score: arr2[index], description: arr3[index], value: arr4[index]}
))
console.log(objects)
This code also works:
var arr = [];
for(var i=0; i<arr1.length; i++) {
arr[i] = {};
arr[i].title = arr1[i];
arr[i].score = arr2[i];
arr[i].description = arr3[i];
arr[i].value = arr4[i];
}
I suggest to use an array of arrays and another array for the keys. This allows an arbitrary count of arrays and keys to use for transforming the data into an array of objects with hte wanted properties.
var array1 = ['Hello', 'World', 'Hi'],
array2 = ['1', '2', '3'],
array3 = ['foo', 'bar', 'foobar'],
array4 = ['10', '20', '30'],
keys = ['title', 'score', 'description', 'value'],
result = [array1, array2, array3, array4].reduce(function (r, a, i) {
a.forEach(function (v, j) {
r[j] = r[j] || {};
r[j][keys[i]] = v;
});
return r;
}, []);
console.log(result);
.as-console-wrapper { max-height: 100% !important; top: 0; }
If you don't want to type the property names twice,
you could do like this:
const descriptor = {
title: arr1,
score: arr2,
description: arr3,
value: arr4
};
const objects = arr1.map((tmp, i) => {
var o = {};
Object.keys(descriptor).forEach(name => o[name] = descriptor[name][i]);
return o;
});
A reducer method would be in place I suppose
const arr1 = ['Hello', 'World', 'Hi', 'Hello2', 'World2', 'Hi2'];
const arr2 = ['1', '2', '3', '11', '22', '33'];
const arr3 = ['foo', 'bar', 'foobar', 'sea', 'shell', 'sea weed'];
const arr4 = ['10', '20', '30', '100', '200', '300'];
const arrays2Objects = arr1.reduce( (obj, next, i) =>
obj.concat({title: next, score: arr2[i], description: arr3[i], value: arr4[i]}),
[]
);
console.log(arrays2Objects);

Sort array of object based on another array

So let's say I have an array:
const chunks = [
{id: 0, names: ['app']},
{id: 1, names: ['contact']},
{id: 2, names: ['bootstrap']}
];
And I want it to be sorted based on the names property, so the order is like in this array:
const original = ['bootstrap', 'app', 'contact'];
What is the most efficient way to do this?
You could use the delta of the indices of names in original.
const chunks = [{ id: 0, names: ['app'] }, { id: 1, names: ['contact'] }, { id: 2, names: ['bootstrap'] }],
original = ['bootstrap', 'app', 'contact'];
chunks.sort((a, b) => original.indexOf(a.names[0]) - original.indexOf(b.names[0]));
console.log(chunks);
.as-console-wrapper { max-height: 100% !important; top: 0; }
Try this method:
const chunks = [{id: 0, names: ['app']}, {id: 1, names: ['contact']}, {id: 2, names: ['bootstrap']}];
const original = ['bootstrap', 'app', 'contact'];
let result = [];
for(let i = 0; i < original.length; i++) {
for(let j = 0; j < chunks.length; j++) {
if(chunks[j].names.indexOf(original[i]) !== -1) {
result.push(chunks[j]);
}
}
}
console.log(result);
Easy way: convert chunks into an object so you get the correct one with just the key, then map over the (already sorted) array to plug in the object in place.
cMap = chunks.reduce((p,c) => Object.assign( p, {[c.names[0]]: c} ), {});
const sorted = original.map(k => cMap[k]);

Without array of objects

I am trying to implement a function similar to lodash _.without but it should work with array of objects:
function withoutArrayOfObjects (arr1, arr2) {
var resultArr = [];
for (var i = 0; i < arr1.length; i++) {
for (var j = 0; j < arr2.length; j++) {
if (!_.isEqual(arr1[i], arr2[j])) {
resultArr.push(arr1[i]);
}
}
}
return resultArr;
}
It woks fine in this case:
var array1 = [{0: 'test', 1: 'test2'}, {0: 'test3', 1: 'test4'}];
var array2 = [{0: 'test', 1: 'test2'}];
withoutArrayOfObjects(array1, array2);
However it fails if array contains two objects:
var array3 = [{0: 'test', 1: 'test2'}, {0: 'test3', 1: 'test4'}, {0: 'test5', 1: 'test6'}, {0: 'test7', 1: 'test8'}];
var array4 = [{0: 'test', 1: 'test2'}, {0: 'test5', 1: 'test6'}];
withoutArrayOfObjects(array3, array4);
Could you help me to fix / improve the function? Either with plain JS or jquery/lodash.
Try this (ES6):
resultArr = arr1.filter(obj1 => {
return !arr2.some(obj2 => _.isEqual(obj1, obj2));
});
Or in ES5:
resultArr = arr1.filter(function (obj1) {
return !arr2.some(function (obj2) {
return _.isEqual(obj1, obj2);
});
});
i.e. We create a new array from arr1 by filtering out items which have some equivalents in arr2.

Categories

Resources