I would like to push key values to objects in array1 from other objects of array2
To do so it needs to search a corresponding values in both arrays, then push the right key.
let array1 = [
{
"Ref": "28189-060-B",
"Otherkey": "Whatever"
},
{
"Ref": "18182-250-B",
"Otherkey": "Whatever2"
},
{
"Ref": "55187-753-B",
"Otherkey": "Whatever3"
}
]
let array2 = [
{
"Ref": "28189-060-ABCD",
"Style": "Red"
},
{
"Ref": "18182-250-ABCD",
"Style": "Blue"
},
{
"Ref": "55187-753-ABCD",
"Style": "Yellow"
}
]
The function need to loop through all objects in array1, look at the first 9 characters of Ref values, find a match in array2 Ref (only first 9 characters are identical). When there is a match push the "Style" from array2 into the corresponding object in array1
I tried with Object.key.foreach(), map(), with substr to get only 9 characters, with find()... all of this has been a big mess and not working...
Expected result :
let array1 = [
{
"Ref": "18182-250-B",
"Otherkey": "Whatever2",
"Style": "Blue"
},
{
"Ref": "28189-060-B",
"Otherkey": "Whatever",
"Style": "Red"
},
{
"Ref": "55187-753-B",
"Otherkey": "Whatever3",
"Style": "Yellow"
}
]
Assuming those properties are all meant to be Ref (some are Global_Style), you can use forEach and find:
let array1 = [{"Ref":"28189-060-B","Otherkey":"Whatever"},{"Ref":"18182-250-B","Otherkey":"Whatever2"},{"Ref":"55187-753-B","Otherkey":"Whatever3"}];
let array2 = [{"Ref":"28189-060-ABCD","Style":"Red"},{"Ref":"18182-250-ABCD","Style":"Blue"},{"Ref":"55187-753-ABCD","Style":"Yellow"}];
const shorterRef = (ref) => ref.substr(0, 9);
array1.forEach(obj => {
const a1Ref = shorterRef(obj.Ref);
const arr2Obj = array2.find(tmp => shorterRef(tmp.Ref) === a1Ref);
if (arr2Obj) obj.Style = arr2Obj.Style;
});
console.log(array1);
If you didn't want to mutate the array go with map:
let array1 = [{"Ref":"28189-060-B","Otherkey":"Whatever"},{"Ref":"18182-250-B","Otherkey":"Whatever2"},{"Ref":"55187-753-B","Otherkey":"Whatever3"}];
let array2 = [{"Ref":"28189-060-ABCD","Style":"Red"},{"Ref":"18182-250-ABCD","Style":"Blue"},{"Ref":"55187-753-ABCD","Style":"Yellow"}];
const shorterRef = (ref) => ref.substr(0, 9);
const out = array1.map(obj => {
const a1Ref = shorterRef(obj.Ref);
const arr2Obj = array2.find(tmp => shorterRef(tmp.Ref) === a1Ref);
if (arr2Obj) return { ...obj, Style: arr2Obj.Style };
});
console.log(out);
var arrMap = {};
array1.forEach(function(x){
if(!arrMap[x.Ref.substring(0,9)]){
arrMap[x.Ref.substring(0,9)] = x;
}
});
array2.forEach(function(x){
if(Object.keys(arrMap).includes(x.Ref.substring(0,9))){
arrMap[x.Ref.substring(0,9)] = Object.assign(arrMap[x.Ref.substring(0,9)], {"Style": x.Style});
}
});
console.log(Object.values(arrMap));
Something like this may be what you want:
array1.forEach(function (element1) {
array2.forEach(function (element2){
addStyle(element1, element2);
});
});
function addStyle(obj1, obj2){
if (obj1.Ref && obj2.Ref){
let Ref1 = obj1.Ref.substr(0,8);
let Ref2 = obj2.Ref.substr(0, 8);
if (Ref1 === Ref2){
obj1.Style = obj2.Style;
};
}
}
So we loop through the fist array and for each item we loop through the second array.
Then we check if the expected fields are present and if so we compare them. If they match we add the "Style" field and move to the next object
The Below code will work although we might be able to optimize it further.
var newArr = []
for(let k in array1){
for(let i in array2){
console.log(array2[i]['Ref'].substr(0,9))
if(array1[k]['Ref'].substr(0,9) == array2[i]['Ref'].substr(0,9)){
let temp = array1[k]
temp['Style'] = array2[i]['Style']
newArr.push(temp)
}
}
}
The first solution is a bit complex.
You probable have a typo in array1 as your first key is not consistent. instead of Global_Stylecode you probably meant Ref, Anyway most likely it should have the same key. If we assume that the key is Ref, then
array1.forEach( ({Ref: Ref1, Otherkey}, index) => {
const Ref1Sub = Ref1.substring(0, 9);
array2.forEach(({Ref: Ref2, Style}) => {
if (Ref2.includes(Ref1Sub)) {
array1[index].Style = Style;
}
})
});
Also there is no need to define arrays as let. const will be fine.
Related
I'm trying to create a JavaScript method which loops over 2 arrays and returns an array of the matched value.
My a1 parameter in the 'getMatchedArray' method is an array of strings and objects, while arr2 is always array of objects.
However, a2 parameter in the 'getMatchedArray' method is an array that can contain an object with value property or without value property as seen in the sample arrays used.
I'm very close to it but somehow not able to figure out, what is the mistake I'm making?
Is there a faster way using intersection to achieve this?
const arr1 = ["red", {
"code": "red",
"label": "test"
}, {
"code": "blue",
"label": "test1"
}, "white", "blue", {
"code": "red",
"label": "test2"
}];
const arr2 = [{
"code": "red",
"value": "test2"
}];
const arr3 = [{
"code": "blue"
}];
const arr4 = [{
"code": "red",
"value": "test3"
}]
function getMatchedArray(a1, a2) {
return a1.reduce((memo, opt) => {
const isOptionFound = a2.some(obj => {
if (obj.value) {
return obj.value === opt.label;
} else {
return !opt.code && opt === obj.code;
}
});
if (isOptionFound) {
memo.push(opt);
}
return memo;
}, []);
}
const result1 = getMatchedArray(arr1, arr2);
const result2 = getMatchedArray(arr1, arr3);
const result3 = getMatchedArray(arr1, arr4);
console.log(result1);
console.log(result2);
console.log(result3);
Expected output:
result1:
[{
"code": "red",
"label": "test2"
}]
result2: ["blue"]
result3: ["red"]
result1, result 2 are fine, but my result3 is incorrect.
Any help on this?
//Try this
function findMatchingValues(arr1, arr2) {
const hashTable = {};
const matchingValues = [];
// Populate hash table with values from arr1
for (let i = 0; i < arr1.length; i++) {
const val = arr1[i];
hashTable[val] = true;
}
// Check arr2 for matching values
for (let i = 0; i < arr2.length; i++) {
const val = arr2[i];
if (hashTable[val]) {
matchingValues.push(val);
}
}
return matchingValues;
}
You can also achieve this requirement by separating the string and object elements from an array and then applied filter on those arrays based on the passed 2nd parameter in the function by stringify the passed parameters in the function.
Live Demo :
const arr1 = ["red", {
"code": "red",
"label": "test"
}, {
"code": "blue",
"label": "test1"
}, "white", "blue", {
"code": "red",
"label": "test2"
}];
const arr2 = [{
"code": "red",
"value": "test2"
}];
const arr3 = [{
"code": "blue"
}];
const arr4 = [{
"code": "red",
"value": "test3"
}];
function getMatchedArray(a1, a2) {
let strA2 = JSON.stringify(a2);
const strArrayFromA1 = a1.filter(item => typeof item === 'string');
const objArrayFromA1 = a1.filter(item => typeof item === 'object');
const matchedObject = objArrayFromA1.filter(elem => {
strA2 = strA2.replaceAll('value', 'label');
return strA2.includes(JSON.stringify(elem));
});
const matchedString = strArrayFromA1.filter(elem => strA2.includes(elem));
return matchedObject.length ? matchedObject : matchedString.length ? matchedString : 'No match found.';
}
const result1 = getMatchedArray(arr1, arr2);
const result2 = getMatchedArray(arr1, arr3);
const result3 = getMatchedArray(arr1, arr4);
console.log(result1);
console.log(result2);
console.log(result3);
The issue with the third result is that the expected output is an array of objects with the matching values, but the current implementation is returning a single object. To fix this, you can modify the function to push the opt value to memo instead of the opt object when there is a match in the arr4.
Here is the modified function:
function getMatchedArray(a1, a2) {
return a1.reduce((memo, opt) => {
const isOptionFound = a2.some(obj => {
if (obj.value) {
return obj.value === opt.label;
} else {
return !opt.code && opt === obj.code;
}
});
if (isOptionFound) {
memo.push(opt.label || opt);
}
return memo;
}, []);
}
With this modification, the output for result3 will be ["red"], which is the expected result.
Regarding the second part of the question, there is a faster way to achieve this using the filter and includes array methods. Here is an example implementation:
function getMatchedArray(a1, a2) {
return a1.filter(opt => {
return a2.some(obj => {
if (obj.value) {
return obj.value === opt.label;
} else {
return opt.code && obj.code && opt.code === obj.code;
}
});
});
}
This implementation uses filter to create a new array with all the elements that match the condition, and includes to check if the a2 array includes the opt value.
I have the below array of objects and I want to check if two different users are present in this array .if present i have to run some logic
let result = [{"name": "ABC"},{"name": "CDE"},{"name": "FGH"},{"name": "XYZ"}];
var newArr = [];
var hasMatch = result.filter(function(val) {
if (val.name == "FGH"){
newArr.push(val)
} else if (val.name == "ABC") {
newArr.push(val)
}
});
console.log(newArr)
if (newArr.length == 2) {
//do logic
}
It's working as expected but I'm looking for a different approach for this. could someone advise?
Not optimized for speed, but does the job
let arr = [
{
"name": "ABC"
},
{
"name": "CDE"
},
{
"name": "FGH"
},
{
"name": "XYZ"
}
];
let users = ["ABC", "XYZ"]
let hasAllUsers = users.every(user => arr.some(item => item.name == user))
console.log(hasAllUsers)
// if(hasAllUser) {...}
It's a pretty roundabout way to zero in on the logic you're trying to express. Note how the result in hasMatch is never even used. That's really all you're looking for, does the array "have the values".
There's no need to push values to another array and check if that array has values. Just check of the original array has them.
Which could be as simple as:
let result = [{"name": "ABC"},{"name": "CDE"},{"name": "FGH"},{"name": "XYZ"}];
if (result.filter(r => r.name === "FGH" || r.name === "ABC").length === 2) {
// do logic
}
Or if you want to refactor the condition into a variable:
let result = [{"name": "ABC"},{"name": "CDE"},{"name": "FGH"},{"name": "XYZ"}];
let hasMatch = result.filter(r => r.name === "FGH" || r.name === "ABC").length === 2;
if (hasMatch) {
// do logic
}
Or a bit more verbose for clarity:
let result = [{"name": "ABC"},{"name": "CDE"},{"name": "FGH"},{"name": "XYZ"}];
let filteredResult = result.filter(r => r.name === "FGH" || r.name === "ABC");
let hasMatch = filteredResult.length === 2;
if (hasMatch) {
// do logic
}
You can simply create another array with the valid users and filter your array to match each items that are this array.
This can be done using the Array#includes method
const users = [{"name": "ABC"},{"name": "CDE"},{"name": "FGH"},{"name": "XYZ"}];
const validUsers = ["ABC", "FGH", "AnotherUser"];
const matchUsers = users.filter(user => validUsers.includes(user.name))
console.log(matchUsers)
You could count the wanted names.
const
data = [{ name: "ABC" }, { name: "CDE" }, { name: "FGH" }, { name: "XYZ" }],
names = ['ABC', 'FGH'],
result = data.reduce((t, { name }) => t + names.includes(name), 0);
console.log(result);
Try using a named function and pass in the array, key, and one or more values with the rest operator ...values. Use .flatMap() to filter with
[...values].includes(obj[key])
// ["ABC", "XYZ"].includes(obj.name)
and any non-match returns an empty array []. The final return is an array with a sub-array and the length of said sub-array.
const result = [["ABC", "XYZ"], 2]
// result[0][0] = "ABC"
// result[0][1] = "XYZ"
// result[1] = 2
const arr = [{"name": "ABC"},{"name": "CDE"},{"name": "FGH"},{"name": "XYZ"}];
function hasMatch(array, key, ...values) {
const result = array.flatMap((obj, idx) =>
[...values].includes(obj[key]) ? obj : []);
return [result, result.length];
}
console.log(hasMatch(arr, "name", "ABC", "XYZ"));
console.log(hasMatch(arr, "name", "FGH", "IJK", "LMN", "ABC", "XYZ"));
I would like to take list variable and get it to the point that updated list is at but am unsure how.
const list = [{name:'apple'},{name:'apple'},{name:'banana'}];
const updatedList = [{name:'apple', count:2},{name:'banana', count: 1}];
Maybe this example will help you ?
const list = [{name:'apple'},{name:'apple'},{name:'banana'}];
const updatedList = Object.values(list.reduce(
(map, el) => {
map[el.name] ? map[el.name].count++ : map[el.name] = { ...el,
count: 1
};
return map;
}, {}
));
console.log(updatedList);
function uptadeLi(list,item,quant) {
// body...
for( i in list){
if (list[i].name === item){
list[i].count = quant
}
}
}
With that function you can set each one of the elements of lists , be sure to put the name of item as string
const list = [{name:'apple'},{name:'apple'},{name:'banana'}];
const res = list.reduce((sub,value)=>{
const index= sub.findIndex(i => i.name===value.name)
if(index !==-1)
sub[index].count++
else
sub.push({name:value.name,count:1})
return sub
},[])
console.log(res)
Use .reduce() method to evaluate the count for each item into an object with unique keys:
{ "apple": 2, "banana": 1 }
Then use Object.entries() to convert this into the following array:
[ ["apple", 2], ["banana", 1] ]
Finally, use .map() method to produce:
[ {"name": "apple", "count": 2}, {"name": "banana", "count": 1} ]
DEMO
const list = [{name:'apple'},{name:'apple'},{name:'banana'}];
const updatedList = Object.entries(
list.reduce(
(acc,cur) => ({...acc,[cur.name]:(acc[cur.name] || 0) + 1}),
{})
)
.map(([name,count]) => ({name,count}));
console.log( updatedList );
I want to add two nested objects in JSON in typescript.
In JSON given below I want to add second JSON's activityLogs item in first JSON's activityLogs.
JSON1:
[{"vehicleno":"SV028","devicE_CODE":"8505","activityLogs":
[{"gpsdate":"01/03/2019","gpstime":"13:40:18"},
{"gpsdate":"01/03/2019","gpstime":"13:38:18"},
{"gpsdate":"01/03/2019","gpstime":"13:37:18"}]
}]
JSON2:
[{"vehicleno":"SV028","devicE_CODE":"8505","activityLogs":
[{"gpsdate":"01/03/2019","gpstime":"13:46:18"},
{"gpsdate":"01/03/2019","gpstime":"13:43:18"}]
}]
Result:
[{"vehicleno":"SV028","devicE_CODE":"8505","activityLogs":
[{"gpsdate":"01/03/2019","gpstime":"13:46:18"},
{"gpsdate":"01/03/2019","gpstime":"13:43:18"},
{"gpsdate":"01/03/2019","gpstime":"13:40:18"},
{"gpsdate":"01/03/2019","gpstime":"13:38:18"},
{"gpsdate":"01/03/2019","gpstime":"13:37:18"}]
}]
How I can do this?
You can use push() with the spread operator or concat and reassign:
var JSON1 = [{"vehicleno":"SV028","devicE_CODE":"8505","activityLogs":[{"gpsdate":"01/03/2019","gpstime":"13:40:18"},{"gpsdate":"01/03/2019","gpstime":"13:38:18"},{"gpsdate":"01/03/2019","gpstime":"13:37:18"}]}]
var JSON2 = [{"vehicleno":"SV028","devicE_CODE":"8505","activityLogs":[{"gpsdate":"01/03/2019","gpstime":"13:46:18"},{"gpsdate":"01/03/2019","gpstime":"13:43:18"}]}]
JSON1[0].activityLogs.push(...JSON2[0].activityLogs)
console.log(JSON1)
This assumes that your json arrays contain just the one top-level object. If that's not the case you need to add more details about how the two arrays are synchronized (for example will vehicleno be the same in both?).
As an example, if the vehicleno is a unique identifier in both arrays you could create a lookup of the JSON1 values and the use that to push into the appropriate arrays. This will update JSON1 in place even if it contains multiple vehicles:
var JSON1 = [{"vehicleno":"SV028","devicE_CODE":"8505","activityLogs":[{"gpsdate":"01/03/2019","gpstime":"13:40:18"},{"gpsdate":"01/03/2019","gpstime":"13:38:18"},{"gpsdate":"01/03/2019","gpstime":"13:37:18"}]}]
var JSON2 = [{"vehicleno":"SV028","devicE_CODE":"8505","activityLogs":[{"gpsdate":"01/03/2019","gpstime":"13:46:18"},{"gpsdate":"01/03/2019","gpstime":"13:43:18"}]}]
let lookup = JSON1.reduce((lookup, obj) => {
lookup[obj.vehicleno] = obj
return lookup
}, {})
JSON2.forEach(obj => lookup[obj.vehicleno].activityLogs.push(...obj.activityLogs))
console.log(JSON1)
You can use concatination array method.
let json1 = [{"vehicleno":"SV028","devicE_CODE":"8505","activityLogs":[{"gpsdate":"01/03/2019","gpstime":"13:40:18"},{"gpsdate":"01/03/2019","gpstime":"13:38:18"},{"gpsdate":"01/03/2019","gpstime":"13:37:18"}]}];
let json2 = [{"vehicleno":"SV028","devicE_CODE":"8505","activityLogs":[{"gpsdate":"01/03/2019","gpstime":"13:46:18"},{"gpsdate":"01/03/2019","gpstime":"13:43:18"}]}]
let result = json1[0].activityLogs.concat(json2[0].activityLogs);
console.log(result);
The simplest way is to concat the activityLogs:
var arr1 = [{
"vehicleno": "SV028",
"devicE_CODE": "8505",
"activityLogs": [{
"gpsdate": "01/03/2019",
"gpstime": "13:40:18"
},
{
"gpsdate": "01/03/2019",
"gpstime": "13:38:18"
},
{
"gpsdate": "01/03/2019",
"gpstime": "13:37:18"
}
]
}];
var arr2 = [{
"vehicleno": "SV028",
"devicE_CODE": "8505",
"activityLogs": [{
"gpsdate": "01/03/2019",
"gpstime": "13:46:18"
},
{
"gpsdate": "01/03/2019",
"gpstime": "13:43:18"
}
]
}];
var arr3 = arr1[0].activityLogs.concat(arr2[0].activityLogs);
console.log(arr3);
.as-console-wrapper {
max-height: 100% !important;
top: auto;
}
Note this will only work if you only have one object in the top-level array.
result = json1;
/// result = Object.assign({}, json1); if you don't want to mutate the original json1
result.forEach(elem1 => elem1.activityLogs
.concat(json2.find(elem2 => elem2.vehicleno === elem1.vehicleno).activityLogs));
Concat the activityLogs of the second array item to the first array item by finding the matching element by vehicleno..
var json1 = [{"vehicleno":"SV028","devicE_CODE":"8505","activityLogs":
[{"gpsdate":"01/03/2019","gpstime":"13:40:18"},
{"gpsdate":"01/03/2019","gpstime":"13:38:18"},
{"gpsdate":"01/03/2019","gpstime":"13:37:18"}]
},{"vehicleno":"SV02","devicE_CODE":"8505","activityLogs":
[{"gpsdate":"01/03/2019","gpstime":"13:40:18"},
{"gpsdate":"01/03/2019","gpstime":"13:38:18"},
{"gpsdate":"01/03/2019","gpstime":"13:37:18"}]
}]
var json2 = [{"vehicleno":"SV028","devicE_CODE":"8505","activityLogs":
[{"gpsdate":"01/03/2019","gpstime":"13:46:18"},
{"gpsdate":"01/03/2019","gpstime":"13:43:18"}]
}];
var jsonCont = json1.concat(json2);
var result = Object.values(jsonCont.reduce((acc, o)=>{
if(!acc.hasOwnProperty(o['vehicleno'])) {
acc[o['vehicleno']] = Object.assign({}, o);
} else {
acc[o['vehicleno']]['activityLogs'] = acc[o['vehicleno']]['activityLogs'].concat(o['activityLogs']);
}
return acc;
}, {}));
console.log(result);
I know the title might sounds confusing, but i'm stuck for an hour using $.each. Basically I have 2 arrays
[{"section_name":"abc","id":1},{"section_name":"xyz","id":2}];
and [{"toy":"car","section_id":1},{"tool":"knife","section_id":1},{"weapons":"cutter","section_id":2}];
How do I put one into another as a new property key like
[{
"section_name": "abc",
"id": 1,
"new_property_name": [{
"toy": "car"
}, {
"tool": "knife"
}]
}, {
"section_name": "xyz",
"id": 2,
"new_property_name": [{
"weapon": "cutter"
}]
}]
ES6 Solution :
const arr = [{"section_name":"abc","id":1},{"section_name":"xyz","id":2}];
const arr2 = [{"toy":"car","id":1},{"tool":"knife","id":1},{"weapons":"cutter","id":2}];
const res = arr.map((section,index) => {
section.new_property_name = arr2.filter(item => item.id === section.id);
return section;
});
EDIT : Like georg mentionned in the comments, the solution above is actually mutating arr, it modifies the original arr (if you log the arr after mapping it, you will see it has changed, mutated the arr and have the new_property_name). It makes the .map() useless, a simple forEach() is indeed more appropriate and save one line.
arr.forEach(section => {
section.new_property_name = arr2.filter(item => item.id === section.id));
});
try this
var data1 = [{"section_name":"abc","id":1},{"section_name":"xyz","id":2}];
var data2 = [{"toy":"car","id":1},{"tool":"knife","id":1},{"weapons":"cutter","id":2}];
var map = {};
//first iterate data1 the create a map of all the objects by its ids
data1.forEach( function( obj ){ map[ obj.id ] = obj });
//Iterate data2 and populate the new_property_name of all the ids
data2.forEach( function(obj){
var id = obj.id;
map[ id ].new_property_name = map[ id ].new_property_name || [];
delete obj.id;
map[ id ].new_property_name.push( obj );
});
//just get only the values from the map
var output = Object.keys(map).map(function(key){ return map[ key ] });
console.log(output);
You could use ah hash table for look up and build a new object for inserting into the new_property_name array.
var array1 = [{ "section_name": "abc", "id": 1 }, { "section_name": "xyz", "id": 2 }],
array2 = [{ "toy": "car", "section_id": 1 }, { "tool": "knife", "section_id": 1 }, { "weapons": "cutter", "section_id": 2 }],
hash = Object.create(null);
array1.forEach(function (a) {
a.new_property_name = [];
hash[a.id] = a;
});
array2.forEach(function (a) {
hash[a.section_id].new_property_name.push(Object.keys(a).reduce(function (r, k) {
if (k !== 'section_id') {
r[k] = a[k];
}
return r;
}, {}));
});
console.log(array1);
Seems like by using Jquery $.merge() Function you can achieve what you need. Then we have concat function too which can be used to merge one array with another.
Use Object.assign()
In your case you can do it like Object.assign(array1[0], array2[0]).
It's very good for combining objects, so in your case you just need to combine your objects within the array.
Example of code:
var objA = [{"section_name":"abc","id":1},{"section_name":"xyz","id":2}];
var objB = [{"toy":"car","section_id":1},{"tool":"knife","section_id":1},{"weapons":"cutter","section_id":2}];
var objC = Object.assign({},objA[0],objB[0]);
console.log(JSON.stringify(objC));// {"section_name":"abc","id":1,"toy":"car","section_id":1}
For more info, you can refer here: Object.assign()
var firstArray = [{"section_name":"abc","id":1},{"section_name":"xyz","id":2}],
secondArray = [{"toy":"car","section_id":1},{"tool":"knife","section_id":1},{"weapons":"cutter","section_id":2}];
var hash = Object.create(null);
firstArray.forEach(s => {
hash[s.id] = s;
s['new_property_name'] = [];
});
secondArray.forEach(i => hash[i['section_id']]['new_property_name'].push(i));
console.log(firstArray);