How to compare two array of objects by mutiple properties using javascript - javascript

I have two array of objects in which if property grp from arrobj1 is
same as SERVICE and ISACTIVE is true from arrobj2, then return array of object using
javascript
Tried
let result = arrobj1.filter(e=>
arrobj2.some(i=> i.ISACTIVE===true && e.grp === i.SERVICE);
);
var arrobj1=[
{
id:"SetupFS",
grp:"fs",
title: "xxx"
},
{
id:"ExtendFS",
grp:"fs",
title: "yyy"
},
{
id:"RebootServer",
grp:"os",
title: "yyy"
},
]
var arrobj2=[
{id:1, ISACTIVE:true, TASK:'SetupFS', SERVICE: "fs" },
{id:2, ISACTIVE:false, TASK:'RebootServer', SERVICE:"os" },
{id:3, ISACTIVE:false, TASK:'ExtendFS', SERVICE: "fs" },
]
Expected Result
[
{
id:"SetupFS",
grp:"fs",
title: "xxx"
}
]

You don't need filter for second item, you need to check if the item with corresponding index in arrobj1 with grp value equal to SERVICE value in arrobj2
var arrobj1=[
{
id:"SetupFS",
grp:"fs",
title: "xxx"
},
{
id:"ExtendFS",
grp:"fs",
title: "yyy"
},
{
id:"RebootServer",
grp:"os",
title: "yyy"
},
]
var arrobj2=[
{id:1, ISACTIVE:true, TASK:'SetupFS', SERVICE: "fs" },
{id:2, ISACTIVE:false, TASK:'RebootServer', SERVICE:"os" },
{id:3, ISACTIVE:false, TASK:'ExtendFS', SERVICE: "fs" },
]
let result = arrobj2.filter((item, i) =>
item.SERVICE === arrobj1[i].grp
);
console.log(result)

A simpler method
// gets two results wit the equals
let filteredList = [];
for (const item of arrobj1) {
// include TASK === item.id to get the expected answer
const inArray = arrobj2.find(e => e.ISACTIVE && e.TASK === item.id && e.SERVICE === item.grp);
if (inArray) {
filteredList.push(item)
}
}
console.log(filteredList)
with filters in the question it returns two items
e => e.ISACTIVE && e.SERVICE === item.grp
0: Object
id: "SetupFS"
grp: "fs"
title: "xxx"
1: Object
id: "ExtendFS"
grp: "fs"
title: "yyy"
Hope it helps
but if this is not what was expected, I'll delete the answer

Related

How to transform nested object of objects into array of objects

Hi all I have the following code
the data that I want to transform.
const obj = {
numbers: {
label: "main numbers",
pageTitle: "Numbers",
key: "1",
items: {
firstNumber: {
label: "first number",
pageTitle: "first",
key: "first"
},
secondNumber: {
label: "second number",
pageTitle: "second",
key: "second"
}
}
},
letters: {
label: "main Letters",
pageTitle: "Letters",
key: "2",
items: {
firstLetter: {
label: "first Letter",
pageTitle: "first",
key: "first"
}
}
},
signs: {
label: "main sign",
pageTitle: "Sign",
key: "3"
}
};
In my obj variable I have 3 other objects
numbers object which has items property which includes 2 other objects.
letters object which has items property which includes only one object.
signs object.
I need to transform my obj to the following way.
[
{
label:"main numbers",
pageTitle:"Numbers",
key:1,
children: [{label,pageTitle,key},{label,pageTitle,key}]
},
{
label:"main Letters",
pageTitle:"Letters",
key:1,
children: [{label,pageTitle,key}]
},
{
label:"main sign",
pageTitle:"Sign",
key:1,
children: []
},
]
for that transformation, I wrote the following code.
const transformedData = Object.values(obj).map((menuitem) => menuitem);
const data = [];
transformedData?.map((x) => {
const newData = {};
newData.label = x.label;
newData.pageTitle = x.pageTitle;
newData.key = x.key;
newData.children = x?.Object?.values(items)?.map((el) => {
newData.children.label = el.label;
newData.children.pageTitle = el.pageTitle;
newData.children.key = el.key;
});
data.push(newData);
});
Everything was working, but for children instead of printing an array it prints undefined.
Please help me to resolve this issue.
I created a function for your case.
const convert = data =>
Object.values(data)?.map(x => ({
label: x.label,
pageTitle :x.pageTitle ,
key: x.pathname,
children: x.items
? Object.values(x.items || {}).map(el => ({ label: el.label,
key:el.pathname,pageTitle:el.pageTitle }))
: null,
}));
You can use like const items = convert(obj).
xdoesn't have Objects. Change it to:
newData.children = Object.values(x.items)?.map(/*...*/);
Is this what you're after?
const transformedData = Object.values(obj).map((menuitem) => menuitem);
const data = [];
transformedData?.map((x) => {
const newData = {};
newData.label = x.label;
newData.pageTitle = x.pageTitle;
newData.key = x.key;
if(x.hasOwnProperty('items')){
newData.children = Object.values(x.items).map((el) => {
const obj={
label:el.label,
pageTitle:el.pageTitle,
key:el.key
}
return obj
})};
data.push(newData);
});
console.log(data)
Your code return undefined because inside map you didn't return anything so newData.children was never populated with anything.
Also, I think accessing and assigning newData.children.label was problematic since there was no newData.children yet. So we declare a temp obj inside map and we return it
Lastly we need to check if items is a property that exists in the first place.

Move object to the subset if the key is matched

[{id:1, name:'Chan', supervisor:''},
{id:2, name:'Wong', supervisor:'1'},
{id:3, name:'Fong', supervisor:'1'},
{id:4, name:'Ho', supervisor:'2'},
]
expected result
[
{
id: 1,
name: "Chan",
supervisor: "",
children: [
{
id: 2,
name: "Wong",
supervisor: "1",
children: [{ id: 4, name: "Ho", supervisor: "2" }]
},
{ id: 3, name: "Fong", supervisor: "1" }
]
}
]
I want to achieve this format like the above. Have tried to use lodash map and filter.
Want to know if there any fastest method to do that? Many thanks in advance.
Currently I have tried.
let children = [];
const transformedDataRecords = records.map((record) => {
let user = _.filter(records, { id: record.supervisor });
if (user.length>0) {
console.log(user[0].children);
if(!!(user[0].children)){
children = user[0].children;
}
children.push(record);
user = { ...user, children };
console.log(user);
}
});
Starting from
const staff = [{id:1, name:'Chan', supervisor:''},
{id:2, name:'Wong', supervisor:'1'},
{id:3, name:'Fong', supervisor:'1'},
{id:4, name:'Ho', supervisor:'2'},
]
This is a nice place to use Maps. You can keep a reference to each object by its ID without having to care about its location in the array:
const staffById = new Map(
// key-value pairs
staff.map(person => [person.id, person])
)
// Create the children arrays
staff.forEach(
person => {
if (person.supervisor !== "") {
// Maps do care about whether data is String or Number so we have to
// convert the supervisor field to Number to ensure they match.
const supervisorParsed = Number(person.supervisor)
const supervisorObj = staffById.get(supervisorParsed)
// Ensure there is an array to insert into
supervisorObj.children = supervisorObj.children || []
supervisorObj.children.push(person)
}
}
)
// References updated, now filter out everyone from the top-level array who is not a top-level supervisor.
const output = staff.filter(person => person.supervisor === '')

Filter string and null values from object

when a value of a property of the object is null or contains "missing" the whole object should be filterd.
this works for filtering null
object = (object.filter(o => !Object.values(o).includes(null))
But how can I add 2 filters and how to implement a filter that filters strings that contain the word "missing"
object = (object.filter(o => !Object.values(o).includes(null) | ("missing")));
object:
[
{ id: 'blockstack-iou',
name: 'Blockstack (IOU)',
image: 'missing_large.png'
}
{ id: 'qtum',
name: 'Qtum',
image:
'https://assets.coingecko.com/coins/images/684/large/qtum.png?1547034438',
price_change_percentage: -53.2869774915231
}
]
Use Array.prototype.every().
Use && to combine multiple tests.
let object = [{
id: 'blockstack-iou',
name: 'Blockstack (IOU)',
image: 'missing_large.png'
},
{
id: 'qtum',
name: 'Qtum',
image: 'https://assets.coingecko.com/coins/images/684/large/qtum.png?1547034438',
price_change_percentage: -53.2869774915231
}
];
console.log(object.filter(o => Object.values(o).every(prop =>
prop != null && !prop.toString().includes("missing"))));
Use && and match
const object = [
{id: 'blockstack-iou',
name: 'Blockstack (IOU)',
image: 'missing_large.png'
},
{ id: 'qtum',
name: 'Qtum',
image:
'https://assets.coingecko.com/coins/images/684/large/qtum.png?1547034438',
price_change_percentage: -53.2869774915231
}
]
const filtered = (object.filter(o =>!Object.values(o).includes(null) && !Object.values(o).toString().match(/missing/gi)));
console.log(filtered)
If you're looking for a solution that is easily extensible, consider storing all your "conditions" as an array and running through them using .every().
const object = [
{str: "this_is_missing"},
{str: null},
{str: "valid"}
];
const validations = [
i => i !== null, //Value isn't null
i => !i.toString().includes("missing") //Value doesn't contain "missing"
];
const validate = (val) => validations.every(fn => fn(val));
const result = object.filter(obj => Object.values(obj).every(validate));
console.log(result);

Check if an array of objects exists

I have an array of objects:
items: [
{ name: "Cheese Puffs", price: 3 },
{ name: "Can of Soda", price: 1.75 }
];
I want to do something like items["cheesePuffs"] === true. But as it is in an array it won't work properly.
What you want is Array.find().
myArrOfObjects.find(el => el.cheesePuffs);
Assuming the property you're looking for is truthy, this returns the element, {cheesePuffs: "yes"} which is truthy. If it weren't found, it would be undefined.
You can use some and hasOwnProperty, If you need actual value instead of Boolean values you can use find instead of some
const myArrOfObjects = [{
cheesePuffs: "yes"
},
{
time: "212"
}];
let findByName = (name) => {
return myArrOfObjects.some(obj=> {
return obj.hasOwnProperty(name)
})
}
console.log(findByName("cheesePuffs"))
console.log(findByName("time"))
console.log(findByName("123"))
okay simple solutions
try this
const x = [{}];
if(x.find(el => el.cheesePuffs) == undefined)
console.log("empty objects in array ")
const myArrOfObjects = [{
cheesePuffs: "yes"
},
{
time: "212"
}];
if(myArrOfObjects.find(el => el.cheesePuffs) == undefined)
console.log("empty objects in array ")
else
console.log("objects available in array ")
As suggestion, you can also decide to not use an array, but to use a json object, where the index of each item is the unique name of your objects (in the example "cheesePuffs" identifies "Cheese Puffs")
let items = {
"cheesePuffs": {name: "Cheese Puffs",price: 3},
"canOfSoda": {name: "Can of Soda",price: 1.75},
};
console.log("exist: ", items.cheesePuffs!== undefined)
console.log(items.cheesePuffs)
// can also access to item in this way:
console.log(items["cheesePuffs"])
console.log("not exist", items.noCheesePuffs!== undefined)
console.log(items.noCheesePuffs)
Try the following code. It will return you the object where name matches to 'Cheese Puffs'.
let items = [{
name: "Cheese Puffs",
price: 3
},
{
name: "Can of Soda",
price: 1.75
}
];
let itemExist = items.find(x => x.name === 'Cheese Puffs');
if (itemExist) {
console.log(itemExist);
} else {
console.log("Item not Exist");
}
You can use find
let exist = myArrOfObjects.find(o => o.cheesePuffs === 'yes')
First of all you have an array of objects so you can't simply use
myArrOfObjects["cheesePuffs"]
because array required an index so it should be myArrOfObjects[0]["cheesePuffs"]
let items = [
{ name: "Cheese Puffs", price: 3 },
{ name: "Can of Soda", price: 1.75 }
];
let filter = items.find( el => el.price === 3 );
console.log(filter);
another approach
let items = [
{ name: "Cheese Puffs", price: 3 },
{ name: "Can of Soda", price: 1.75 }
];
let filter = items.filter( el => el.price === 3 );
console.log(filter);

How to rename fileds in object or fetch it's data to other object with new field?

I didn't find the answer here, so please to do no write that it is duplicate!
My problem is as follows. I have such an array with objects:
Items: [
{ groups: [{…}]
id: 1
name: "Test Name"
_test: null
_test2: 0.02867696
},
{ groups: [{…}]
id: 2
name: "Test Name2"
_test: null
_test2: 0.02867696
},
]
I need to change each object fields names, such as id, name to topicId and topicName. The rest on the data I need to keep as it is and return back array with changed objects.
I wrote such a function to get access to every object:
function changeFields(data) {
for (const key of Object.keys(data)) {
data[key].map(item => {
})
}
}
but I do not know what to do next.
As per your question you are trying to modify existing array of objects. Below are the pseudo steps
Loop through array using map or any equivalent method
Clone the object
Add new property with desired key to cloned object and it's value will be value associated with existing key
Delete old key from the object
Below is the sample code for your data and in that code i am modifying key id to _id
var data = [
{
groups: [{}],
id: 1,
name: "Test Name",
_test: null,
_test2: 0.02867696
},
{
groups: [{}],
id: 2,
name: "Test Name2",
_test: null,
_test2: 0.02867696
}
];
var modifiedData = data.map((item) => {
let _item = Object.assign(item, {});
_item['_id'] = item['id'];
delete _item['id'];
return _item;
});
console.log(modifiedData);
You can use map method of array to modify each entry and reassign it.
let Items = [
{
groups: [
1, 2
],
id: 1,
name: "Test Name",
_test: null,
_test2: 0.02867696
}, {
groups: [
1, 2
],
id: 2,
name: "Test Name2",
_test: null,
_test2: 0.02867696
}
]
Items = Items.map(item => ({
group : item.group,
topicId : item.id,
topicName : item.name,
_test : item._test,
_test2 :item._test2
}))
Or you have many field in array and only want to change one or two filed you can write general solution like this :
Items = Items.map(item => {
let obj = {};
//Loop trough each fields of item
Object.keys(item).filter(key => {
switch (key) {
//Fields to be changed
case 'id':
obj['topicId'] = item['id']
break;
case 'name':
obj['topicName'] = item['name']
break;
//End
//Rest will be the same
default:
obj[key] = item[key]
}
})
//Return modified obj
return obj;
})

Categories