Javascript: How Do you Combine Two Objects Into One [duplicate] - javascript

This question already has answers here:
Javascript equivalent of Python's zip function
(24 answers)
Is there a ways to combine objects in Javascript
(1 answer)
Closed 3 years ago.
I am trying to combine two object arrays using either Javascript or Jquery but it is not resulting the way I am expecting it to be. These are my array objects results:
Arry1 Results: [{"name": "2412"}, {"name": "3324"}, {"name": "8875"}]
Arry2 Results: [{"zip": "12051"}, {"zip": "54021"}, {"zip": "24521"}]
This is what I have done to push one into the other:
Array.prototype.push.apply(Arry1,Arry2);
The issue is the above code stacks them together. The object structure I am trying to get is as follows:
[
{
"name": "2412",
"zip": "12051"
},
{
"name": "3324",
"zip": "54021"
},
{
"name": "8875",
"zip": "24521"
}
]

Map the arrays into each other by cloning and combining with Object.assign
let a1 = [{"name": "2412"}, {"name": "3324"}, {"name": "8875"}];
let a2 = [{"zip": "12051"}, {"zip": "54021"}, {"zip": "24521"}];
let result = a1.map((props, index) => Object.assign(props, a2[index]));
console.log(result);
Edit Based on Comment:
If this is a utility you're going to be using often with a variable number of arrays, you may consider creating a function that handles it.
let a1 = [{"name": "2412"}, {"name": "3324"}, {"name": "8875"}],
a2 = [{"zip": "12051"}, {"zip": "54021"}, {"zip": "24521"}],
a3 = [{"phone": "1234"},{"phone": "3121"},{"phone": "2136"}];
function combine(first, ...arrs) {
let result = first.map((props, index) => {
let combined = [props];
arrs.forEach(arr => combined.push(arr[index]));
return Object.assign(...combined);
})
return result;
};
let result = combine(a1, a2, a3);
console.log(result);

You can use map:
const arr1 = [{"name": "2412"}, {"name": "3324"}, {"name": "8875"}];
const arr2 = [{"zip": "12051"}, {"zip": "54021"}, {"zip": "24521"}];
let result = arr1.map((obj, idx) => {
obj.zip = arr2[idx].zip;
return obj
});
console.log(result)

There are multiple ways to do this. The below is one of,
let array1 = [{"name": "2412"}, {"name": "3324"}, {"name": "8875"}];
let array2 = [{"zip": "12051"}, {"zip": "54021"}, {"zip": "24521"}];
let resultArray = [];
for(let i=0; i< array1.length; i++) { // we can consider any of array1 or array 2 length
resultArray.push({...array1[i], ...array2[i]});
}
console.log(resultArray);
OR
With Jquery, we can go like below,
let array1 = [{ name: "2412" }, { name: "3324" }, { name: "8875" }];
let array2 = [{ zip: "12051" }, { zip: "54021" }, { zip: "24521" }];
let resultArray = [];
$.each(array1, function(index, value) {
resultArray.push($.extend(value, array2[index]));
});
console.log(resultArray);

Related

If I use lodash's union to merge objects based on a set of boolean settings, how would one write it elegantly?

I've encountered a programming problem I've never encountered before. I am merging object data based on user defined settings. Does anyone know how to program this without a bunch of (inelegant) nested if/else statements? _union takes an array.
import _ from 'lodash';
// Real data structure is more complex, but is an array that contains objects like so
let dataset1 = [{ "name": "John" }, { "name": "Paul" }];
let dataset2 = [{ "name": "Laura" }, { "name": "Eline" }];
let dataset3 = [{ "name": "Boris" }, { "name": "Tanya" }];
// These are use configurable settings, real dataset is user defined
let dataSetActive1 = true;
let dataSetActive2 = true;
let dataSetActive3 = false;
// this is the dataset I need in this case of true, true, false - but how to
// write this elegantly when the truth/false changes?
let dataset = _.union(dataset1, dataset2);
My favorite way to do that would be:
let dataset1 = [{
"name": "John"
}, {
"name": "Paul"
}];
let dataset2 = [{
"name": "Laura"
}, {
"name": "Eline"
}];
let dataset3 = [{
"name": "Boris"
}, {
"name": "Tanya"
}];
let dataSetActive1 = true;
let dataSetActive2 = true;
let dataSetActive3 = false;
let dataset = _.union(
dataSetActive1 && dataset1,
dataSetActive2 && dataset2,
dataSetActive3 && dataset3
)
.filter(Boolean);
console.log(dataset)
<script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.17.15/lodash.min.js"></script>
filter(Boolean) will filter out all the falsy values from the array, which will be when your setting is false.
Use a ternary to return an empty array for each Active variable/const which is false.
Since the items in your array are objects _.union(), which uses the SameValueZero algorithm ,would never find and remove duplicates. Because if Object A, and Object B are not the same object, they are not equal. Use _.unionBy() with the name as the iteratee used as the uniqueness criterion.
const dataset1 = [{ "name": "John" }, { "name": "Paul" }];
const dataset2 = [{ "name": "Laura" }, { "name": "Eline" }];
const dataset3 = [{ "name": "Boris" }, { "name": "Tanya" }];
const dataSetActive1 = true;
const dataSetActive2 = true;
const dataSetActive3 = false;
const result = _.unionBy(
dataSetActive1 ? dataset1 : [],
dataSetActive2 ? dataset2 : [],
dataSetActive3 ? dataset3 : [],
'name'
);
console.log(result)
<script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.17.15/lodash.min.js"></script>

Iterate through Nested Array in JavaScript

I'm trying to Iterate through a nested array and having trouble extracting the correct value.
My Json FIle
var regions = [
{
"id": 265592,
"longName": "Amsterdam 1",
"name": "ams01",
"statusId": 2,
"regions": [
{
"description": "AMS01 - Amsterdam",
"keyname": "AMSTERDAM",
"sortOrder": 0
}
]
},
{
"id": 814994,
"longName": "Amsterdam 3",
"name": "ams03",
"statusId": 2,
"regions": [
{
"description": "AMS03 - Amsterdam",
"keyname": "AMSTERDAM03",
"sortOrder": 26
}
]
},
{
"id": 1004997,
"longName": "Chennai 1",
"name": "che01",
"statusId": 2,
"regions": [
{
"description": "CHE01 - Chennai ",
"keyname": "CHENNAI",
"sortOrder": 30
}
]
},
I would like to extract only the Key name from the Regions Array into an Array.
MY code which works fine and gives me the output:
const regions3 = []
for (let i = 0; i < regions.length; i++) {
const element = regions[i];
const regions1 = (element.regions)
for (let j = 0; j < regions1.length; j++) {
const element1 = regions1[j];
const element2 = element1.keyname;
regions3.push(element2)
console.log(regions3)
}
}
Output
AMSTERDAM
AMSTERDAM03
CHENNAI
I would like to know if there a faster way to iterate rather than running it into two for loops??
Thank you
You can use Array.flatMap() (not supported in IE/Edge) with Array.map():
const regions = [{"id":265592,"longName":"Amsterdam 1","name":"ams01","statusId":2,"regions":[{"description":"AMS01 - Amsterdam","keyname":"AMSTERDAM","sortOrder":0}]},{"id":814994,"longName":"Amsterdam 3","name":"ams03","statusId":2,"regions":[{"description":"AMS03 - Amsterdam","keyname":"AMSTERDAM03","sortOrder":26}]},{"id":1004997,"longName":"Chennai 1","name":"che01","statusId":2,"regions":[{"description":"CHE01 - Chennai ","keyname":"CHENNAI","sortOrder":30}]}]
const result = regions.flatMap(o =>
o.regions.map(p => p.keyname)
)
console.log(result)
If you can't use Array.flatMap() you can use an external Array.map() and spread the results into Array.concat() instead:
const regions = [{"id":265592,"longName":"Amsterdam 1","name":"ams01","statusId":2,"regions":[{"description":"AMS01 - Amsterdam","keyname":"AMSTERDAM","sortOrder":0}]},{"id":814994,"longName":"Amsterdam 3","name":"ams03","statusId":2,"regions":[{"description":"AMS03 - Amsterdam","keyname":"AMSTERDAM03","sortOrder":26}]},{"id":1004997,"longName":"Chennai 1","name":"che01","statusId":2,"regions":[{"description":"CHE01 - Chennai ","keyname":"CHENNAI","sortOrder":30}]}]
const result = [].concat(...regions.map(o =>
o.regions.map(p => p.keyname)
))
console.log(result)
You can use .map() and destructuring assignment
var regions = [{"id":265592,"longName":"Amsterdam 1","name":"ams01","statusId":2,"regions":[{"description":"AMS01 - Amsterdam","keyname":"AMSTERDAM","sortOrder":0}]},{"id":814994,"longName":"Amsterdam 3","name":"ams03","statusId":2,"regions":[{"description":"AMS03 - Amsterdam","keyname":"AMSTERDAM03","sortOrder":26}]},{"id":1004997,"longName":"Chennai 1","name":"che01","statusId":2,"regions":[{"description":"CHE01 - Chennai ","keyname":"CHENNAI","sortOrder":30}]}];
let res = regions.map(({regions: [{keyname}]}) => keyname);
console.log(res);
Another solution for this is using Array::reduce():
var regions = [{"id":265592,"longName":"Amsterdam1","name":"ams01","statusId":2,"regions":[{"description":"AMS01-Amsterdam","keyname":"AMSTERDAM","sortOrder":0}]},{"id":814994,"longName":"Amsterdam3","name":"ams03","statusId":2,"regions":[{"description":"AMS03-Amsterdam","keyname":"AMSTERDAM03","sortOrder":26}]},{"id":1004997,"longName":"Chennai1","name":"che01","statusId":2,"regions":[{"description":"CHE01-Chennai","keyname":"CHENNAI","sortOrder":30}]}];
let res = regions.reduce(
(acc, curr) => (curr.regions.forEach(x => acc.push(x.keyname)), acc),
[]
);
console.log(res);
Well its pretty much the same thing but using a forEach method or array type in javascript can save you some time. here is an example.
const regions3 = [];
regions.forEach(function(region){
region.regions.forEach(function(subRegion){
regions3.push(subRegion.keyname);
console.log(subRegion.keyname);
})
});
a forEach executes an anonymous function passing each element in array as the argument to the anonymous function

Lodash to find if object property exists in array

I have an array of objects like this:
[ {"name": "apple", "id": "apple_0"},
{"name": "dog", "id": "dog_1"},
{"name": "cat", "id": "cat_2"}
]
I want to insert another element, also named apple, however, because I don't want duplicates in there, how can I use lodash to see if there already is an object in the array with that same name?
You can use Lodash _.find() like this.
var data = [ {"name": "apple", "id": "apple_0"},
{"name": "dog", "id": "dog_1"},
{"name": "cat", "id": "cat_2"}
]
if(!_.find(data, {name: 'apple'})) {
data.push({name: 'apple2'});
}
console.log(data)
<script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.15.0/lodash.min.js"></script>
Reference documentation: https://lodash.com/docs/4.17.14#find
This is Form
_.has(object, path)
Example:
const countries = { country: { name: 'Venezuela' } }
const isExist = _.has(countries, 'country.name')
// isExist = true
For more information Document Lodash
You can use Array.prototype.find() or lodash's _.find():
const addItem = (arr, item) => {
if(!arr.find((x) => x.name === item.name)) { // you can also change `name` to `id`
arr.push(item);
}
};
const arr = [
{"name": "apple", "id": "apple_0"},
{"name": "dog", "id": "dog_1"},
{"name": "cat", "id": "cat_2"}
];
addItem(arr, { "name": "apple", "id": "apple_0" });
addItem(arr, { "name": "pear", "id": "pear_3" });
console.log(arr);
And a bit shorter but less readable version:
const addItem = (arr, item) => arr.find((x) => x.name === item.name) || arr.push(item); // you can also change `name` to `id`
const arr = [
{"name": "apple", "id": "apple_0"},
{"name": "dog", "id": "dog_1"},
{"name": "cat", "id": "cat_2"}
];
addItem(arr, { "name": "apple", "id": "apple_0" });
addItem(arr, { "name": "pear", "id": "pear_3" });
console.log(arr);
Here is an other example with lodash
var a = [ {"name": "apple", "id": "apple_0"},
{"name": "dog", "id": "dog_1"},
{"name": "cat", "id": "cat_2"}
]
var b = _.find(a, ['name', "apple2"]);
if(_.isObject(b)){
console.log('exists')
}else{
console.log('insert new')
}
https://jsfiddle.net/jorge182/s4og07jg/
This is what worked for me (after testing out the different solutions):
addItem(items, item) {
let foundObject = _.find(items, function(e) {
return e.value === item.value;
});
if(!foundObject) {
items.push(item);
}
return items;
}
If you're interested in inserting in the array only one value, then using _.find could be an option. However, if you were interested in inserting one or more than one, I'd suggest using _.unionBy instead:
var currentArr = [{
"name": "apple",
"id": "apple_0"
}, {
"name": "dog",
"id": "dog_1"
}, {
"name": "cat",
"id": "cat_2"
}],
arrayOneValue = [{
"name": "apple",
"id": "apple_0"
}],
arrayTwoValues = arrayOneValue.concat({
"name": "lemon",
"id": "lemon_0"
})
console.log(_.unionBy(currentArr, arrayOneValue, 'name'));
console.log(_.unionBy(currentArr, arrayTwoValues, 'name'));
// It also allow you to perform the union using more than one property
console.log(_.unionBy(currentArr, arrayTwoValues, 'name', 'id'));
<script src="https://cdn.jsdelivr.net/lodash/4.16.4/lodash.min.js"></script>
Here are three ways of achieving this using lodash 4.17.5:
Say you want to add object entry to an array of objects numbers, only if entry does not exist already.
let numbers = [
{ to: 1, from: 2 },
{ to: 3, from: 4 },
{ to: 5, from: 6 },
{ to: 7, from: 8 },
{ to: 1, from: 2 } // intentionally added duplicate
];
let entry = { to: 1, from: 2 };
/*
* 1. This will return the *index of the first* element that matches:
*/
_.findIndex(numbers, (o) => { return _.isMatch(o, entry) });
// output: 0
/*
* 2. This will return the entry that matches. Even if the entry exists
* multiple time, it is only returned once.
*/
_.find(numbers, (o) => { return _.isMatch(o, entry) });
// output: {to: 1, from: 2}
/*
* 3. This will return an array of objects containing all the matches.
* If an entry exists multiple times, if is returned multiple times.
*/
_.filter(numbers, _.matches(entry));
// output: [{to: 1, from: 2}, {to: 1, from: 2}]
/*
* 4. This will return `true` if the entry exists, false otherwise.
*/
_.some(numbers, entry);
// output: true
If you want to return a Boolean (i.e., assuming that you are not using _.some()), in the first case, you can simply check the index value that is being returned:
_.findIndex(numbers, (o) => { return _.isMatch(o, entry) }) > -1;
// output: true
Lodash documentation is great source of examples and experimentation.

Sorting First Array With The Order Of Second Array

Suppose I am having two arrays namely namesArray and names as below
var namesArray = [{"name":"Charlie","age":3},{"name":"Dog","age":1},{"name":"Baker","age":7},{"name":"Abel","age":9}];
var names = ['Baker', 'Dog', 'Abel', 'Charlie'];
Can I achieve the following in UnderscoreJS so that sort the array named namesArray in a order so that all the name elements of namesArray will be in the same order of names .
In plain Javascript, you could use Array#sort with an object as reference for the sort order.
var namesArray = [{ "name": "Charlie", "age": 3 }, { "name": "Dog", "age": 1 }, { "name": "Baker", "age": 7 }, { "name": "Abel", "age": 9 }],
names = ['Baker', 'Dog', 'Abel', 'Charlie'],
hash = Object.create(null);
names.forEach(function (a, i) {
hash[a] = i + 1;
});
namesArray.sort(function (a, b) {
return (hash[a.name] || 0) - (hash[b.name] || 0);
});
console.log(namesArray);
Look up the index of each name in sort(). Not as performant as creating hash of indexes but chances are it's not that critical either
namesArray.sort(function(a,b){
return names.indexOf(a.name) - names.indexOf(b.name);
});
There is not lot to do with underscrore but you can do it like this:
I think using hash like what Nina does would be better than indexOf with respect to performance.
var namesArray = [{ "name": "Charlie", "age": 3 }, { "name": "Dog", "age": 1 }, { "name": "Baker", "age": 7 }, { "name": "Abel", "age": 9 }];
var names = ['Baker', 'Dog', 'Abel', 'Charlie'];
var sorted = _.sortBy(namesArray, o => names.indexOf(o.name));
console.log(sorted);
<script src="https://cdnjs.cloudflare.com/ajax/libs/underscore.js/1.8.3/underscore.js"></script>

Convert a two dimensional array into an array of objects

I have a two dimensional array, datas, that I want to convert to an array of objects.
The keys are in datas[0], I want to extract them, name, child, and size. and then append each attribute to it to get a master object. For some reason it overrides and is only showing one object when I try this?
var test = new Object();
for (i = 0; i < datas.length; i++){
var obj = new Object();
obj.name = datas[i][0];
obj.parent = datas[i][1];
obj.size = datas[i][2];
test.update(obj);
}
I would like the final result to be:
[
{"name": "Billy", "parent":"Ann", "size": "1"},
{"name": "Ben", "parent": "John", "size": "1"},
etc...
]
The datas array looks like:
[["Name", "Parent", "Size"], ["Billy", "Ann", "1"], ["Ben", "John", "1"] ... ]
You can't make an object without properties, so your desired result can't be achieved.
Assuming you want:
[
{"name": "Billy", "parent": "Ann", "size": "1"},
{"name": "Ben", "parent": "John", "size": "1"},
etc...
]
Try:
var test = [];
for(i = 0; i < datas.length; i++){
test.push({
name: datas[i][0],
parent: datas[i][1],
size: datas[i][2]
});
}
// do something with test
{
{"name": "Billy", "parent":"Ann", "size"="1"},
{"name": "Ben", "parent": "John", "size" = "1"}
}
is not correct json. curly braces mean - object, object must be presented in key:value form. There are two possible correct json of this kind:
array of objects
[
{"name": "Billy", "parent":"Ann", "size"="1"},
{"name": "Ben", "parent": "John", "size" = "1"}
]
deep structure
{
"Billy" {"parent":"Ann", "size"="1"},
"Ben" {"parent": "John", "size" = "1"}
}
to generate first variant
var res = []
for(i = 0; i<datas.length; i++){
var obj = new Object();
obj.name = datas[i][0];
obj.parent = datas[i][1];
obj.size = datas[i][2];
res.push(obj);
}
JSON.stringify(res);
to generate second variant
var res = new Object();
for(i = 0; i<datas.length; i++){
var obj = new Object();
obj.parent = datas[i][1];
obj.size = datas[i][2];
res.[datas[i][0]] = obj;
}
JSON.stringify(res);

Categories

Resources