I have array of objects as follows:
[
{
company: "CompanyName",
id: "1",
userProfile: {
id: "2",
telephone: "",
user: {
email: "some_email",
firstName: "Firstname",
lastName: "Lastname",
groups: [
{id: "2", name: "Manager"},
{id: "10", name: "Remarketing Manager"}
]
}
}
},
{
company: "CompanyName",
id: "2",
userProfile: {
id: "3",
telephone: "",
user: {
email: "some_email",
firstName: "Firstname",
lastName: "Lastname",
groups: [
{id: "1", name: "Seller"}
]
}
}
},
{
company: "CompanyName",
id: "3",
userProfile: {
id: "4",
telephone: "",
user: {
email: "some_email",
firstName: "Firstname",
lastName: "Lastname",
groups: [
{id: "2", name: "Manager"}
]
}
}
}
]
I want to count by group name.
Thus the result that I want is:
{
"Manager": 2,
"Seller": 1,
"Remarketing Manager": 1,
}
I tried with lodash countBy as follows:
countBy(users, 'userProfile.user.groups.name');
But it doesn't work.
Here is the fiddle.
Flatten the arrays of groups with _.flatMap(), and then count by name:
const data = [{"company":"CompanyName","id":"1","userProfile":{"id":"2","telephone":"","user":{"email":"some_email","firstName":"Firstname","lastName":"Lastname","groups":[{"id":"2","name":"Manager"},{"id":"10","name":"Remarketing Manager"}]}}},{"company":"CompanyName","id":"2","userProfile":{"id":"3","telephone":"","user":{"email":"some_email","firstName":"Firstname","lastName":"Lastname","groups":[{"id":"1","name":"Seller"}]}}},{"company":"CompanyName","id":"3","userProfile":{"id":"4","telephone":"","user":{"email":"some_email","firstName":"Firstname","lastName":"Lastname","groups":[{"id":"2","name":"Manager"}]}}}]
const result = _.countBy(_.flatMap(data, 'userProfile.user.groups'), 'name')
console.log(result)
<script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.17.11/lodash.js"></script>
You can use reduce
let data = [{company: "CompanyName",id: "1",userProfile: {id: "2",telephone: "",user: {email: "some_email",firstName: "Firstname",lastName: "Lastname",groups: [{id: "2", name: "Manager"},{id: "10", name: "Remarketing Manager"}]}}},{company: "CompanyName",id: "2",userProfile: {id: "3",telephone: "",user: {email: "some_email",firstName: "Firstname",lastName: "Lastname",groups: [{id: "1", name: "Seller"}]}}},{company: "CompanyName",id: "3",userProfile: {id: "4",telephone: "",user: {email: "some_email",firstName: "Firstname",lastName: "Lastname",groups: [{id: "2", name: "Manager"}]}}}]
let final = data.reduce((op,{userProfile:{user:{groups}}}) => {
groups.forEach(({name}) => {
op[name] = op[name] || 0
op[name]++
})
return op
},{})
console.log(final)
Related
I have such an object with newComments:
const newComments = {
commentDirectoryId: "ee63997c-01d5-ec11-8dad-e116bd673e14",
comments: [
{
id: "123",
status: {
entity: null,
id: "1a913152-7809-ec11-8daa-90600b960f93",
name: "In work",
parentId: null,
},
},
{
id: "124",
status: {
entity: null,
id: "1a913152-7809-ec11-8daa-90600b960f94",
name: "Note",
parentId: null,
},
},
{
id: "125",
status: {
entity: null,
id: "1a913152-7809-ec11-8daa-90600b960f95",
name: "Canceled",
parentId: null,
},
},
{
id: "126",
status: {
entity: null,
id: "1a913152-7809-ec11-8daa-90600b960f96",
name: "Done",
parentId: null,
},
},
],
dataType: "Tags",
idAttributeApprovalName: "12-015-123",
};
There are also filters:
const values = ["Note", "Canceled", "Done"];
My task is to return only comments that are not equal to keys:
comment.status.name !== "Note" | "Canceled" |"Done"
In other words:
const newComments = {
commentDirectoryId: "ee63997c-01d5-ec11-8dad-e116bd673e14",
comments: [
{
id: "123",
status: {
entity: null,
id: "1a913152-7809-ec11-8daa-90600b960f93",
name: "In work",
parentId: null,
},
},
],
dataType: "Tags",
idAttributeApprovalName: "12-015-123",
};
You can use Array#filter in conjunction with Array#every or Array#includes.
const newComments={commentDirectoryId:"ee63997c-01d5-ec11-8dad-e116bd673e14",comments:[{id:"123",status:{entity:null,id:"1a913152-7809-ec11-8daa-90600b960f93",name:"In work",parentId:null}},{id:"124",status:{entity:null,id:"1a913152-7809-ec11-8daa-90600b960f94",name:"Note",parentId:null}},{id:"125",status:{entity:null,id:"1a913152-7809-ec11-8daa-90600b960f95",name:"Canceled",parentId:null}},{id:"126",status:{entity:null,id:"1a913152-7809-ec11-8daa-90600b960f96",name:"Done",parentId:null}},],dataType:"Tags",idAttributeApprovalName:"12-015-123"};
const values = ["Note", "Canceled", "Done"];
newComments.comments = newComments.comments.filter(c =>
values.every(v => c.status.name !== v));
// or !values.includes(c.status.name) if no complex matching logic is required
console.log(newComments);
I am writing code in ReactJs
I have an Array of object like this
[
{
createdBy: "DEF",
createdDate: "2020",
lastModifiedDate: "2021",
name: "John Doe",
section: {
createdBy: "A2C",
status: "ACTIVE",
},
sectionName: "Mechanical",
},
{
createdBy: "ABC",
createdDate: "2020",
lastModifiedDate: "2021",
name: "John Doe",
section: {
createdBy: "ABC",
status: "ACTIVE",
},
sectionName: "Mechanical",
},
{
createdBy: "ABC",
createdDate: "2020",
lastModifiedDate: "2021",
name: "John Doe",
section: {
createdBy: "XYZ",
status: "ACTIVE",
},
sectionName: "Mechanical",
},
{
createdBy: "A1C",
createdDate: "2020",
lastModifiedDate: "2021",
name: "John Wick",
section: {
createdBy: "ABC",
status: "ACTIVE",
},
sectionName: "Mechanical",
},
];
here, the only thing same is the "name", so on the basis of name, I want the duplicate objects to be stored in the new array.
I have tried it like this
let temp = [];
for (const i of response) {
if (!temp.includes(i)) {
temp.push(i);
console.log("if loop", i);
} else {
console.log("else loop", response);
}
}
but the control never goes to else as it considers each object as different.
I need the first occurrence of an object as it is, but when the "name" element gets repeated, that object should get stored in a new array.
Expected:-
[
{
createdBy: "ABC",
createdDate: "2020",
lastModifiedDate: "2021",
name: "John Doe",
section: {
createdBy: "ABC",
status: "ACTIVE",
},
sectionName: "Mechanical",
},
{
createdBy: "ABC",
createdDate: "2020",
lastModifiedDate: "2021",
name: "John Doe",
section: {
createdBy: "XYZ",
status: "ACTIVE",
},
sectionName: "Mechanical",
},
]
You can maintain a tracker object for checking if an object with the same name has already been visited or not. If visited then push the object into a duplicate array otherwise push into unique array. Try this-
const data=[{createdBy:"ABC",createdDate:"2020",lastModifiedDate:"2021",name:"John Doe",section:{createdBy:"ABC",status:"ACTIVE"},sectionName:"Mechanical"},{createdBy:"ABC",createdDate:"2020",lastModifiedDate:"2021",name:"John Doe",section:{createdBy:"A2C",status:"ACTIVE"},sectionName:"Mechanical"},{createdBy:"A1C",createdDate:"2020",lastModifiedDate:"2021",name:"John Doe",section:{createdBy:"ABC",status:"ACTIVE"},sectionName:"Mechanical"}];
const track = {};
const unique = [];
const duplicate = [];
for (const item of data) {
if (track?.[item.name] === undefined) {
unique.push(item);
track[item.name] = true;
} else {
duplicate.push(item);
}
}
console.log('unique', unique);
console.log('duplicate', duplicate);
.as-console-wrapper {min-height: 100%!important; top: 0}
let count=0
let temp = response;
let duplicateArray=[]
for (const i of response) {
count=0
if(temp.find(t => t.name === i.name)){
count++
}
if(count>0){
duplicateArray.push(i)
}
}
Not sure if this will solve the particular issue you have but
not use helprjs
const arr1 = [{ id: 1, name: 'Jack'}, { id: 2, name: 'Jack'}];
const arr2 = [{ id: 2, name: 'Jane'}, { id: 3, name: 'Rod'}];
mergeArrays(arr1, arr2, "name");
// [{ id: 1, name: 'Jack'}, { id: 2, name: 'Jane'}, { id: 3, name: 'Rod'}];
mergeArrays(arr1, arr2, "id");
// [{ id: 1, name: 'Jack'}, { id: 2, name: 'Jack'}, { id: 3, name: 'Rod'}];
Check out the demo
let project = {
title: "some title",
participants: [{
_id: "12345678",
name: "John"
}, {
_id: "44332211",
name: "Jackson"
}, {
_id: "55667788",
name: "Steve"
}]
}
let users = [{
_id: "12345678",
name: "John"
}, {
_id: "44332211",
name: "Jackson"
}, {
_id: "09876543",
name: "Aaron"
}, {
_id: "55667788",
name: "Steve"
}, {
_id: "22334455",
name: "Xavier"
}]
How do I list out all the users that are NOT part of the project participants? includes does not work because project is an object...
array.filter + array.some will work:
let project = {
title: "some title",
participants: [{
_id: "12345678",
name: "John"
}, {
_id: "44332211",
name: "Jackson"
}, {
_id: "55667788",
name: "Steve"
}]
}
let users = [{
_id: "12345678",
name: "John"
}, {
_id: "44332211",
name: "Jackson"
}, {
_id: "09876543",
name: "Aaron"
}, {
_id: "55667788",
name: "Steve"
}, {
_id: "22334455",
name: "Xavier"
}]
let result = users.filter(user => !project.participants.some(p => p._id === user._id));
console.log(result);
You can also make use of find with filter:
var users = [{ _id: "12345678", name: "John"}, { _id: "44332211", name: "Jackson"}, { _id: "09876543", name: "Aaron"}, { _id: "55667788", name: "Steve"}, { _id: "22334455", name: "Xavier"}];
var project = { title: "some title", participants: [{ _id: "12345678", name: "John" }, { _id: "44332211", name: "Jackson" }, { _id: "55667788", name: "Steve" }]};
var result = users.filter(k=>!project.participants.find(p=>p._id==k._id));
console.log(result);
Using Array.map and Array.filter
let project = { title: "some title",
participants: [{_id: "12345678", name: "John"},
{_id: "44332211", name: "Jackson"},
{_id: "55667788", name: "Steve"}]
}
let users = [{ _id: "12345678", name: "John"},
{ _id: "44332211", name: "Jackson"},
{ _id: "09876543", name: "Aaron"},
{ _id: "55667788", name: "Steve"},
{ _id: "22334455", name: "Xavier"}];
var participants = project.participants.map(function(p){ return p._id; })
var non_participants = users.filter(function(user){
return participants.indexOf(user._id) == -1;
});
console.log(non_participants);
I would first extract the participant ids into a Set for fast lookup. Then filter the users and check if the id is not included in the set (using has).
let project = {
title: "some title",
participants: [
{ _id: "12345678", name: "John" },
{ _id: "44332211", name: "Jackson" },
{ _id: "55667788", name: "Steve" },
]
};
let users = [
{ _id: "12345678", name: "John" },
{ _id: "44332211", name: "Jackson" },
{ _id: "09876543", name: "Aaron" },
{ _id: "55667788", name: "Steve" },
{ _id: "22334455", name: "Xavier" },
];
const participantIds = new Set(project.participants.map(participant => participant._id));
const usersWithoutProject = users.filter(user => !participantIds.has(user._id));
console.log(usersWithoutProject);
Initially, I'm having the object:
let root = {};
root["myRootNode"] = {
id1: {
age: "17",
name: "name1",
surname: "surname1"
},
id2: {
age: "11",
name: "name2",
surname: "surname2"
},
id3: {
age: "25",
name: "name1",
surname: "surname3"
}
};
And what I want to do with it, is to get it into the state:
"name1": [
{
age: "17",
surname: "surname1"
},
{
age: "25",
surname: "surname3"
}
],
"name2": [
age: "11",
surname: "surname2"
]
For me it's important to have the list/array of all objects, which contains this same property, grouped by the value of that property.
What I tried (using lodash) is:
let test = _.mapKeys(root["myRootNode"], function(value, key) {
return value["name"];
});
But this gives me the result:
"name1": {
age: "25"
name: "name1"
surname: "surname3"
},
"name2": {
age: "11"
name: "name2"
surname: "surname2"
}
So they are not grouped and only the last value is mapped under the key which is repeating. Also in the result that I got, they are not placed under an array.
Can use groupBy and map it's values to get rid of the name property.
If you don't mind leaving the name property can simply do _.groupBy(root.myRootNode, 'name');
Personally it feels like you should be using arrays instead of objects
const res =
_(root.myRootNode)
.groupBy('name')
.mapValues((arr)=>_.map(arr, (o) =>_.omit(o,['name'])))
.value()
console.log(res)
<script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.17.10/lodash.min.js"></script>
<script>
let root = {};
root["myRootNode"] = {
id1: {
age: "17",
name: "name1",
surname: "surname1"
},
id2: {
age: "11",
name: "name2",
surname: "surname2"
},
id3: {
age: "25",
name: "name1",
surname: "surname3"
}
};
</script>
Here's a shot at it. The idea is to create an array for each new name and push all entries onto the corresponding name array.
const root = {
myRootNode: {
id1: {
age: "17",
name: "name1",
surname: "surname1"
},
id2: {
age: "11",
name: "name2",
surname: "surname2"
},
id3: {
age: "25",
name: "name1",
surname: "surname3"
}
}
};
const result = Object.values(root.myRootNode).reduce((a, e) => {
if (!(e.name in a)) {
a[e.name] = [];
}
a[e.name].push({
age: e.age,
surname: e.surname
});
return a;
}, {});
console.log(JSON.stringify(result, null, 4));
I have a filter function that is returning undefined only when JSON is passed into it. I'd like to use this function to filter objects, JSON or anything really. Whats the best way to make this work on both objects and JSON?
let a = [{
"employees": {
"employee": [{
"id": "1",
"firstName": "Tom",
"lastName": "Cruise"
}, {
"id": "2",
"firstName": "Maria",
"lastName": "Sharapova"
}, {
"id": "3",
"firstName": "James",
"lastName": "Bond"
}]
}
}];
var b = [{
name: '',
grade: 'x'
}, {
name: 'yaya',
grade: 'x'
}, {
name: 'x',
frade: 'd'
}, {
name: 'a',
grade: 'b'
}];
function findIt(arr, searchKey) {
return arr.filter(obj => Object.keys(obj).some(key => obj[key].includes(searchKey)));
}
if (a) {
console.log("I found: ", findIt(a, "James")); // breaks
}
if (b) {
console.log("I found: ", findIt(b, "yaya")); // works fine
}
You need a reference to the inner array for searching.
findIt(a[0].employees.employee, "James"));
// ^^^^^^^^^^^^^^^^^^^^^^
let a = [{ employees: { employee: [{ id: "1", firstName: "Tom", lastName: "Cruise" }, { id: "2", firstName: "Maria", lastName: "Sharapova" }, { id: "3", firstName: "James", lastName: "Bond" }] } }];
var b = [{ name: '', grade: 'x' }, { name: 'yaya', grade: 'x' }, { name: 'x', frade: 'd' }, { name: 'a', grade: 'b' }];
function findIt(arr, searchKey) {
return arr.filter(obj => Object.keys(obj).some(key => obj[key].includes(searchKey)));
}
console.log(findIt(a[0].employees.employee, "James"));
console.log(findIt(b, "yaya"));
For a deeper find, you could use an recursive approach.
function findIt(object, search) {
function find(k) {
if (object[k] === search) {
return result = object;
}
return result = findIt(object[k], search);
}
var result;
if (object && typeof object === 'object') {
Object.keys(object).some(find);
}
return result;
}
var a = [{ employees: { employee: [{ id: "1", firstName: "Tom", lastName: "Cruise" }, { id: "2", firstName: "Maria", lastName: "Sharapova" }, { id: "3", firstName: "James", lastName: "Bond" }] } }],
b = [{ name: '', grade: 'x' }, { name: 'yaya', grade: 'x' }, { name: 'x', frade: 'd' }, { name: 'a', grade: 'b' }];
console.log(findIt(a, "James"));
console.log(findIt(b, "yaya"));
console.log(findIt(a, "foo")); // undefined
.as-console-wrapper { max-height: 100% !important; top: 0; }
You can try to do a string search.
Logic
Create a copy of object but as string using JSON.stringify
Create a regex that searches for a pattern :<something>SearchValue.
Test object string with this regex and return it in filter
let a = [{ employees: { employee: [{ id: "1", firstName: "Tom", lastName: "Cruise" }, { id: "2", firstName: "Maria", lastName: "Sharapova" }, { id: "3", firstName: "James", lastName: "Bond" }] } }];
var b = [{ name: '', grade: 'x' }, { name: 'yaya', grade: 'x' }, { name: 'x', frade: 'd' }, { name: 'a', grade: 'b' }];
function findIt(arr, searchKey) {
let reg = new RegExp(':(.*?)' + searchKey, 'g');
return arr.filter(obj => reg.test(JSON.stringify(obj)));
}
console.log("I found: ", findIt(a, "James")); // breaks
console.log("I found: ", findIt(a[0].employees.employee, "James")); // breaks
console.log("I found: ", findIt(b, "yaya")); // works fine