Comparing property of object with property of another array - javascript

I am having difficulty comparing properties of two objects/arrays
First object
{
"62ac1c8d5b25ad28781a586d": {
"selectedOption": 0
},
"62ac1c8d5b25ad28781a586e": {
"selectedOption": 0
}}
Second Array
[
{
"question_id": "62ac1c8d5b25ad28781a586d",
"selected_ans": 0
},
{
"question_id": "62ac1c8d5b25ad28781a586e",
"selected_ans": 0
},
{
"question_id": "62ac1c8d5b25ad28781a586f",
"ans": 0
}
]
Kindly suggest how to compare the initial property of first object(example: 62ac1c8d5b25ad28781a586d) with the question_id property of second array and return only the matching question_id

You can filter elements from secondArr using Set as:
const obj = {
'62ac1c8d5b25ad28781a586d': {
selectedOption: 0,
},
'62ac1c8d5b25ad28781a586e': {
selectedOption: 0,
},
};
const secondArr = [
{
question_id: '62ac1c8d5b25ad28781a586d',
selected_ans: 0,
},
{
question_id: '62ac1c8d5b25ad28781a586e',
selected_ans: 0,
},
{
question_id: '62ac1c8d5b25ad28781a586f',
ans: 0,
},
];
const keys = new Set(Object.keys(obj));
const result = secondArr.filter((o) => keys.has(o.question_id));
console.log(result);

You could simply use the find method defined on the array prototype.
function compare(id, arr){
return arr.find(arrObj => arrObj.question_id === id);
}
To find all the matching ids from the object present in the array, you could loop through the keys and call the compare function for those keys like this.
function compare(id, arr) {
return arr.find(arrObj => arrObj.question_id === id);
}
const obj = {
"62ac1c8d5b25ad28781a586d": {
"selectedOption": 0
},
"62ac1c8d5b25ad28781a586e": {
"selectedOption": 0
}
}
const arr = [
{
"question_id": "62ac1c8d5b25ad28781a586d",
"selected_ans": 0
},
{
"question_id": "62ac1c8d5b25ad28781a586e",
"selected_ans": 0
},
{
"question_id": "62ac1c8d5b25ad28781a586f",
"ans": 0
}
]
const matchingObjects = [];
for (let key in obj) {
const matchObject = compare(key, arr);
if (matchObject) {
matchingObjects.push(matchObject);
}
}
console.log(matchingObjects);

Related

Editing/Adding value in object of objects

Main problem is that key format is not supported for selecting.
I do have automatically generated object list with unique keys.
Index and key is known. I do need to add value to custom_property object or edit if it already exists.
Code snapshot:
let initialValue = {
"126ccbb5-1a89-40a9-9393-6849a2f502bc": {
"uuid": "126ccbb5-1a89-40a9-9393-6849a2f502bc",
"order": 0,
"custom_properties": {
},
},
"82945a12-ffcb-4dba-aced-e201fa9a531e": {
"uuid": "82945a12-ffcb-4dba-aced-e201fa9a531e",
"order": 1,
"custom_properties": {
},
}
}
I do have these values that I want to insert/update on the custom_property array
const index = 0;
const name = "some_title"
const value = {value: 1, label: "some label"}
How result should look like:
let initialValue = {
"126ccbb5-1a89-40a9-9393-6849a2f502bc": {
"uuid": "126ccbb5-1a89-40a9-9393-6849a2f502bc",
"order": 0,
"custom_properties": {
"some_title" : {value: 1, label: "some label"}
},
},
"82945a12-ffcb-4dba-aced-e201fa9a531e": {
"uuid": "82945a12-ffcb-4dba-aced-e201fa9a531e",
"order": 1,
"custom_properties": {
},
}
}
You can try using Object.values() and get the array of items and then pass down the index like,
Object.values(data)[index]
Then assign the dynamic key-value to the custom_properties like,
item.custom_properties = {
[name]: value,
};
Working Snippet:
let initialValue = {
'126ccbb5-1a89-40a9-9393-6849a2f502bc': {
uuid: '126ccbb5-1a89-40a9-9393-6849a2f502bc',
order: 0,
custom_properties: {},
},
'82945a12-ffcb-4dba-aced-e201fa9a531e': {
uuid: '82945a12-ffcb-4dba-aced-e201fa9a531e',
order: 1,
custom_properties: {},
},
};
const index = 0;
const name = 'some_title';
const value = { value: 1, label: 'some label' };
const getUpdatedResult = (data) => {
const item = Object.values(data)[index];
if (item) {
item.custom_properties = {
[name]: value,
};
}
return data;
};
console.log(getUpdatedResult(initialValue));
you can do something like this
const update = (data, index, key, value) =>
Object.fromEntries(Object.entries(data).map(([k, v], i) => i === index? [k, {...v, custom_properties: Object.assign({}, v.custom_properties, {[key]: value})}]:[k,v]))
let initialValue = {
"126ccbb5-1a89-40a9-9393-6849a2f502bc": {
"uuid": "126ccbb5-1a89-40a9-9393-6849a2f502bc",
"order": 0,
"custom_properties": {},
},
"82945a12-ffcb-4dba-aced-e201fa9a531e": {
"uuid": "82945a12-ffcb-4dba-aced-e201fa9a531e",
"order": 1,
"custom_properties": {},
}
}
const newValue = update(initialValue, 0, 'newKey', 'newValue')
console.log(newValue)

In typescript the filtering the array is not working

filtervalue = {
serviceLine:['cca','ga']
}
this.inProgresDetailsData = [{serviceLine:'cca'}, { serviceLine:'cca'}, { serviceLine:'bca'}]
this.hrResourceDetailsdata= this.inProgresDetailsData.filter(item => {
for (let index = 0; index < filterValue.serviceLine.length; index++) {
item.serviceLine == filterValue.serviceLine[index]
}
});`
this.hrResourceDetailsdata is empty on filtering
The Array.prototype.filter (documentation) function expects you to return a boolean value that decides whether to keep the current item or not.
Since you are originally not returning any value, you implicitly return undefined which when checked against a boolean resolves to false, hence, all of your array items are discarded one by one, leaving none remaining.
You want to return the boolean to make this work:
this.hrResourceDetailsdata = this.inProgresDetailsData.filter(item => {
for (let index = 0; index < filterValue.serviceLine.length; index++) {
if (item.serviceLine == filterValue.serviceLine[index]) {
return true; // return true if found, otherwise continue
}
}
return false; // filter is never found in loop, fall back to false
});
Also, you can use Array.prototype.includes (documentation) to simplify your check, the following code does the exact same thing:
this.hrResourceDetailsdata = this.inProgresDetailsData.filter(item => {
// return true if `item.serviceLine` is inside `filterValue.serviceLine`
return filterValue.serviceLine.includes(item.serviceLine);
});
You can create a Set out of filterValue.serviceLine and filter out the items that are present in the set.
const
filterValue = { serviceLine: ["cca", "ga"] },
inProgressDetailsData = [
{ serviceLine: "cca" },
{ serviceLine: "cca" },
{ serviceLine: "bca" },
],
filterSet = new Set(filterValue.serviceLine),
hrResourceDetailsdata = inProgressDetailsData.filter(({ serviceLine }) =>
filterSet.has(serviceLine)
);
console.log(hrResourceDetailsdata);
If you want to apply multiple filters, then:
Create an object containing filters in form of Sets.
Filter items where all the filters are applicable using Array.prototype.every.
const
filterValue = {
serviceLine: ["cca", "ga"],
urgency: ["medium", "high"],
},
filterSet = Object.fromEntries(
Object.entries(filterValue).map(([k, v]) => [k, new Set(v)])
),
inProgressDetailsData = [
{ id: 1, urgency: "low", serviceLine: "cca" },
{ id: 2, urgency: "medium", serviceLine: "cca" },
{ id: 3, urgency: "low", serviceLine: "bca" },
{ id: 4, urgency: "high", serviceLine: "ga" },
{ id: 5, urgency: "low", serviceLine: "abc" },
],
hrResourceDetailsdata = inProgressDetailsData.filter((data) =>
Object.entries(filterSet).every(([k, v]) => v.has(data[k]))
);
console.log(hrResourceDetailsdata);
Code
filtervalue = {
serviceLine:['cca','ga']
};
this.inProgresDetailsData = [
{ serviceLine:'cca'},
{ serviceLine:'cca'},
{ serviceLine:'bca'}
];
this.hrResourceDetailsdata = this.inProgresDetailsData.filter(item => {
return filtervalue.serviceLine.includes(item.serviceLine)
});
console.log(this.hrResourceDetailsdata)

Json Array compare with different length in javascript

Below code which I am using for creating the new array if the id is the same in arr1 and arr2. But doesn't work since arr1 and arr2 are different. array 1 has index and arr2 is without index. screenshot for your reference. Can someone help?
Note: ID in arr1 is the same as EmpId in arr2
for(let i=0; i<arr1.length; i++) {
merged.push({
...arr1[i],
...(arr2.find((itmInner) => itmInner.id === arr1[i].id))}
);
}
console.log(merged);
Array1 looks like this :
[{"Active":1,"Id":1},
{"Active":1,"Id":3},
{"Active":1,"Id":2}]
Array2 looks something like this:
Below is the sample code on how I am framing array 2:
renderElement(activity){
var arr2 = [] ;
for(var i = 0; i < activity.length; i++) {
obj = activity[i];
if(obj.Id == 28){
fetch(geturl)
.then(function (response) {
return response.json();
})
.then(function (data) {
res = data;
arr2.push(res)
})
}
else{
// Do nothing
}
}
return arr2
}
Calling Render method like below:
outputarray = currentComponent.renderElement(activity);
console.log('output', outputarray)
Expected Output:
[{"Active":1,"Id":1,"Param1": true},
{"Active":1,"Id":3}, / Keep it as such if nothing exists in other array
{"Active":1,"Id":2, "Param2": false}]
You can try this approach instead:
Example #1
const arr1 = [
{ "Active":1, "Id":1 },
{ "Active":1, "Id":3 },
{ "Active":1, "Id":2 }
];
const arr2 = [
{
0: [
{
EmpId1: 1, Param1: true
}
]
},
{
1: [
{
EmpId2: 2,Param2: false
}
]
},
{
2: [
{
EmpId3: 2
}
]
},
];
const response = arr1
.reduce((acc, value) => {
const secondaryData = arr2.map((val, index) => {
const { [`EmpId${index + 1}`]: Id, ...others } = val[Object.keys(val)][0];
return { Id, ...others };
});
const match = secondaryData.findIndex(({ Id }) => Id === value.Id);
if (match >= 0) acc.push({...value, ...secondaryData[match]})
else acc.push(value);
return acc;
}, []);
console.log(response);
Example #2
const arr1 = [
{ "Active":1, "Id":1 },
{ "Active":1, "Id":3 },
{ "Active":1, "Id":2 }
];
const arr2 = [
[
{
EmpId1: 1,
Param1: true
}
],
[
{
EmpId2: 2,
Param2: false
}
],
[
{
EmpId3: 2
}
],
]
const response = arr1
.reduce((acc, value) => {
const secondaryData = arr2.map(([val], index) => {
const { [`EmpId${index + 1}`]: Id, ...others } = val;
return { Id, ...others };
});
const match = secondaryData.findIndex(({ Id }) => Id === value.Id);
if (match >= 0) acc.push({...value, ...secondaryData[match]})
else acc.push(value);
return acc;
}, []);
console.log(response);
Basically you can create a hash map by a object property and join on that property all the arrays, i.e. reduce an array of arrays into a result object, then convert the object's values back to an array. Since each array is reduced this means each array is only traversed once O(n) and the map object provides constant time O(1) lookup to match objects. This keeps the solution closer to O(n) rather than other solutions with a nested O(n) findIndex search, which yields a solution closer to O(n^2).
const mergeByField = (...arrays) => {
return Object.values(
arrays.reduce(
(result, { data, field }) => ({
...data.flat().reduce(
(obj, el) => ({
...obj,
[el[field]]: {
...obj[el[field]],
...el
}
}),
result
)
}),
{}
)
);
};
Load each array into a payload object that specifies the field key to match on. This will return all fields used to match by, but these can safely be ignored later, or removed, whatever you need. Example:
mergeByField(
{ data: arr1, field: "Id" },
{ data: arr2, field: "EmpId" },
);
const arr1 = [
{
Active: 1,
Id: 1
},
{
Active: 1,
Id: 2
},
{
Active: 1,
Id: 3
}
];
const arr2 = [[{ EmpId: 1, Param1: true }], [{ EmpId: 3, Param2: false }]];
const mergeByField = (...arrays) => {
return Object.values(
arrays.reduce(
(result, { data, field }) => ({
...data.flat().reduce(
(obj, el) => ({
...obj,
[el[field]]: {
...obj[el[field]],
...el
}
}),
result
)
}),
{}
)
);
};
console.log(
mergeByField({ data: arr1, field: "Id" }, { data: arr2, field: "EmpId" })
);

How to dedupe an array of objects by a key value pair?

// This is a large array of objects, e.g.:
let totalArray = [
{"id":"rec01dTDP9T4ZtHL4","fields":
{"user_id":170180717,"user_name":"abcdefg","event_id":516575,
}]
let uniqueArray = [];
let dupeArray = [];
let itemIndex = 0
totalArray.forEach(x => {
if(!uniqueArray.some(y => JSON.stringify(y) === JSON.stringify(x))){
uniqueArray.push(x)
} else(dupeArray.push(x))
})
node.warn(totalArray);
node.warn(uniqueArray);
node.warn(dupeArray);
return msg;
I need my code to identify duplicates in the array by a key value of user_id within the objects in the array. Right now, my code works to identify identical objects in the array, but I need it to identify dupes based on a key value inside the objects instead. How do I do this? I am struggling to figure out how to path the for each loop to identify the dupe based on the key value instead of the entire object.
Right now, my code works to identify identical objects in the array, but I need it to identify dupes based on a key value inside the objects instead. How do I do this?
Don’t compare the JSON representation of the whole objects then, but only their user_id property specifically.
totalArray.forEach(x => {
if(!uniqueArray.some(y => y.fields.user_id === x.fields.user_id)){
uniqueArray.push(x)
} else(dupeArray.push(x))
})
You could take a Set and push to either uniques or duplicates.
var array = [
{ id: 1, data: 0 },
{ id: 2, data: 1 },
{ id: 2, data: 2 },
{ id: 3, data: 3 },
{ id: 3, data: 4 },
{ id: 3, data: 5 },
],
uniques = [],
duplicates = [];
array.forEach(
(s => o => s.has(o.id) ? duplicates.push(o) : (s.add(o.id), uniques.push(o)))
(new Set)
);
console.log(uniques);
console.log(duplicates);
.as-console-wrapper { max-height: 100% !important; top: 0; }
One way is to keep a list of ids you found so far and act accordingly:
totalArray = [
{ id: 1, val: 10 },
{ id: 2, val: 20 },
{ id: 3, val: 30 },
{ id: 2, val: 15 },
{ id: 1, val: 50 }
]
const uniqueArray = []
const dupeArray = []
const ids = {}
totalArray.forEach( x => {
if (ids[x.id]) {
dupeArray.push(x)
} else {
uniqueArray.push(x)
ids[x.id] = true
}
})
for (const obj of uniqueArray) console.log("unique:",JSON.stringify(obj))
for (const obj of dupeArray) console.log("dupes: ",JSON.stringify(obj))

How to remove a common property from each array which is nested

I have an array like below: I want to remove origin: 0 property and add it value directly using Javascript es6 feature. How to remove same repeated property from a nested array.
const orginalData = {
name: {
origin: 0,
value: 'christi'
},
location: {
origin: 0,
value: 'Blr'
},
address: {
origin: 0,
value: [{
"streetAddress1": {
"origin": 0,
"value": '12th street'
},
"city1": {
"origin": 0,
"value": 'Maxwell'
}
},
{
"streetAddress2": {
"origin": 0,
"value": '10=]]]]]]]th street'
},
"city2": {
"origin": 0,
"value": 'Coxwell'
}
}
]
}
}
const finalData = {
name: 'christi',
location: 'Blr',
address: [{
streetAddress1: '10th street',
city1: 'Maxwell'
},
{
streetAddress2: '12th street',
city2: 'Coxwell'
}
]
}
You could create generic function like this. reduce the entries of an object to remove a level of nesting and update with nested value. If value as an array, recursively call the function on each object using map and get an array of restructured objects. This will work for any level of nesting
const orginalData={name:{origin:0,value:"christi"},location:{origin:0,value:"Blr"},address:{origin:0,value:[{streetAddress1:{origin:0,value:"12th street"},city1:{origin:0,value:"Maxwell"}},{streetAddress2:{origin:0,value:"10=]]]]]]]th street"},city2:{origin:0,value:"Coxwell"}}]}};
function restructure(obj) {
return Object.entries(obj).reduce((acc, [k, { value }]) => {
acc[k] = Array.isArray(value) ? value.map(restructure) : value;
return acc;
}, {})
}
const finalData = restructure(orginalData)
console.log(finalData)
If you're using NodeJs you could use omit-deep to remove any property you want, regardless of where it is within the object.
For example, this:
const omitDeep = require('omit-deep');
const data = {
name: { origin: 0, value: 'christi' },
location: { origin: 0, value: 'Blr' },
address: {
origin: 0,
value: [
{ streetAddress1: { origin: 0, value: '12th street' }, city1: { origin: 0, value: 'Maxwell' } },
{ streetAddress2: { origin: 0, value: '10=]]]]]]]th street' }, city2: { origin: 0, value: 'Coxwell' } }
]
}
};
const finalData = omitDeep(data, 'origin');
Produces this result:
{
name: { value: 'christi' },
location: { value: 'Blr' },
address: {
value: [
{ streetAddress1: { value: '12th street' }, city1: { value: 'Maxwell' } },
{ streetAddress2: { value: '10=]]]]]]]th street' }, city2: { value: 'Coxwell' } }
]
}
};
first if you want to edit your data, it can't be a const, so change const by let or var.
second
you can use for loop to do that, you can juste write a function or add a function to JSON object
// first logique as global function
function keepKey(data, keep) {
for(let key in data) data[key] = data[key][keep];
}
// second logique as global function
function removeKey(data, remove, assignRest) {
for(let key in data){
//get the item
let item = data[key];
if(typeof item === 'object'){
//if you put 'use strict' at the top you have to use a loop
let temp = {}, lastKey = '';
for(let itemKey in item){
if(itemKey !== remove){
if(assignRest === true) temp = item[itemKey];
else temp[itemKey] = item[itemKey];
}
}
data[key] = temp;
//else you can use directly delete
//delete item[remove];
}
}
}
// add the function to JSON object
JSON.keepKey = {...function...}
// or
JSON.removeKey = {...function...}
JSON.keepKey(orginalData, 'value');
// will give you
{name: 'christi',location: 'Blr',...}
JSON.removeKey(orginalData, 'value', true);
// will give you
{name: 'christi',location: 'Blr',...}
JSON.removeKey(orginalData, 'value', false);
// will give you
{name: {value : 'christi'},location: {value: 'Blr'},...}
const finalData = {
// ...originalData, uncommnent this if you have more originalData has props that you do not want to chnage.
name: originalData.name.value,
location: originalData.location.value,
address: originalData.address.value.map(item => {
const { origin, ...rest } = item;
return rest;
}),
};
This is just a copy of adiga's logic, made more explicit with extraneous identifiers and comments.
It's intended to help with understanding of the reduce method (and other JavaScript features) and of recursion.
const originalData = {
name: { origin: 0, value: 'christi' },
location: { origin: 0, value: 'Blr' },
address: {
origin: 0,
value: [
{
"streetAddress1": { "origin": 0, "value": '12th street' },
"city1": { "origin": 0, "value": 'Maxwell' }
},
{
"streetAddress2": { "origin": 0, "value": '10=]]]]]]]th street' },
"city2": { "origin": 0, "value": 'Coxwell' }
}
]
}
};
function restructure(obj) {
// Whether `restructure` is called directly or recursively, it builds and returns
// a new object.
return Object.entries(obj).reduce( (acc, curr, ind, arr ) => {
// Here, `entries` is a 2D array where each 'row' is a property and the two
// 'columns' are the property name and property value.
// We identify them explicitly below and assume that that the property value
// is an object with a subproperty called "value", which we also identify.
const propKey = curr[0], propVal = curr[1], subpropVal = propVal["value"];
// Logs the index (ie 'row' number) of the current property and its property name
//console.log(ind, propKey);
// Here, `acc` is the object we will return. We give `acc` a new property with
// the same name as the current property.
// If the "value" subproperty of the current property holds an array, the new
// property will hold an array of objects, each of which is a `restructure`d
// version of an object from the source array. (This can happen many times,
// restructuring nested objects from many nested arrays.)
// If not, the new property will have the same value as the "value" subproperty does
acc[propKey] = Array.isArray(subpropVal) ? subpropVal.map(restructure) : subpropVal;
// If this call to `restructure` was recursive, we will continue looping through
// the array we are currently processing.
// If this was the original call, we're done and log our `finalData` to the console.
return acc;
}, {})
}
const finalData = restructure(originalData);
console.log(finalData);

Categories