I have an object like this;
var authList = {
"first": [{
Id: 1,
name: "test1"
}, {
Id: 2,
name: "test2"
}, {
Id: 3,
name: "test3"
}],
"second": [{
Id: 3,
name: "test3"
}],
"third": [{
Id: 2,
name: "test2"
}, {
Id: 3,
name: "test3"
}],
...may be n unit
};
how do i get users that are in each array?
example out;
response = [{ Id: 3, name: "test3" }];
In set theory terms you want to find the intersection between the sets of users. While JavaScript can transform arrays into sets, it does not have an intersection function but you can mix arrays and sets and use filters instead:
var authList = {
"first": [{
Id: 1,
name: "test1"
}, {
Id: 2,
name: "test2"
}, {
Id: 3,
name: "test3"
}],
"second": [{
Id: 3,
name: "test3"
}],
"third": [{
Id: 2,
name: "test2"
}, {
Id: 3,
name: "test3"
}],
};
let values = Object.values(authList);
let result = values[0].map(x => x.Id);
for(let i=1; i<values.length;i++) {result = result.filter(x => new Set(values[i].map(x => x.Id)).has(x))}
console.log(result);
This snippet creates an array of ids and stores them in the result variable, in this case the result = [3]. If you want the whole object instead you can use a map to map identifiers to objects again.
var authList = {
"first": [{
Id: 1,
name: "test1"
}, {
Id: 2,
name: "test2"
}, {
Id: 3,
name: "test3"
}],
"second": [{
Id: 3,
name: "test3"
}],
"third": [{
Id: 2,
name: "test2"
}, {
Id: 3,
name: "test3"
}],
};
let users = []
Object.keys(authList).map((res) => {
authList[res].map(res => {
users.push(res)
})
})
console.log('users', users)
this code works
var authList = {
"first": [{ Id: 1, name: "test1" }, { Id: 2, name: "test2" }, { Id: 3, name: "test3" }],
"second": [{ Id: 3, name: "test3" }],
"third": [{ Id: 2, name: "test2" }, { Id: 3, name: "test3"],
};
var keys = Object.keys(authList);
var resultArray = null;
for (var j = 0; j < keys.length; j++) {
if (!resultArray) {
resultArray = authList[keys[j]];
}
var sArray = authList[keys[j + 1]];
if (sArray) {
resultArray = resultArray.filter(a => sArray.some(b => a.Id === b.Id));
}
}
console.log(resultArray);
Here's a solution from pilchard's idea. Utilizing Array#reduce function to traverse the entire value set and find out the common items:
var authList = {
"first": [{
Id: 1,
name: "test1"
}, {
Id: 2,
name: "test2"
}, {
Id: 3,
name: "test3"
}],
"second": [{
Id: 3,
name: "test3"
}],
"third": [{
Id: 2,
name: "test2"
}, {
Id: 3,
name: "test3"
}]
};
const commonItems = Object.values(authList).reduce((acc, cur) =>
acc.filter(obj1 => cur.find(obj2 =>
Object.entries(obj2).every(([k, v]) => obj1[k] === v))
)
);
console.log(commonItems);
Related
How can I get the result from arr1 and arr2, When the ID matches I need to copy the content from arr1
const arr1 = [
{ id: 1, name: "omar" },
{ id: 2, name: "laith" },
{ id: 3, name: "aref" },
]
const arr2 = [
{ id: 1, rating: "good" },
{ id: 2, rating: "very good" },
{ id: 2, rating: "very good" },
{ id: 3, rating: "Excellence" },
{ id: 3, rating: "Excellence" },
]
//expected output
const result = [
{ id: 1, rating: "good", name: "omar" },
{ id: 1, rating: "good", name: "omar" },
{ id: 2, rating: "very good", name: "laith" },
{ id: 3, rating: "Excellence", name: "aref" },
{ id: 3, rating: "Excellence", name: "aref" },
]
use reduce with filter
const arr1 = [ { id: 1, name: "omar" }, { id: 2, name: "laith" }, { id: 3, name: "aref" }, ];
const arr2 = [ { id: 1, rating: "good" }, { id: 2, rating: "very good" }, { id: 2, rating: "very good" }, { id: 3, rating: "Excellence" }, { id: 3, rating: "Excellence" }, ];
const result = arr1.reduce((acc,item) => {
const list = arr2.filter(i => i.id === item.id)
return [...acc, ...list.map(i => ({id: i.id,rating:i.rating, name: item.name}))]
}, [])
console.log(result)
Basically with a loop. Actually 2. Using a temporary object (result) as dictionary (or map) we can make it efficient searching for a match to each id. This is of complexity O(n) basically.
const arr1 = [ { id: 1, name: "omar" }, { id: 2, name: "laith" }, { id: 3, name: "aref" }, ];
const arr2 = [ { id: 1, rating: "good" }, { id: 2, rating: "very good" }, { id: 2, rating: "very good" }, { id: 3, rating: "Excellence" }, { id: 3, rating: "Excellence" }, ];
var result = {}
arr1.forEach(function(item1) {
result[item1.id] = item1;
});
arr2.forEach(function(item2) {
result[item2.id] = (result[item2.id] || item2)
result[item2.id]['rating'] = item2.rating
})
result = Object.values(result)
console.log(result)
I have array like this, my id and name will be same for multiple objects but organizations values can be different
array= [
{id: 1, name: "Test1", organizations: 1},
{id: 1, name: "Test1", organizations: 2},
{id: 1, name: "Test1", organizations: 3},
{id: 2, name: "Test2", organizations: 4},
{id: 2, name: "Test2", organizations: 5},
{id: 2, name: "Test2", organizations: 6}
];
I want to convert this to be like this:
expectedArray = [
{id: 1, name: "Test1", organizations: [1,2,3]},
{id: 2, name: "Test2", organizations: [4,5,6]}
];
Can someone please help
const array= [
{id: 1, name: "Test1", organizations: 1},
{id: 1, name: "Test1", organizations: 2},
{id: 1, name: "Test1", organizations: 3},
{id: 2, name: "Test2", organizations: 4},
{id: 2, name: "Test2", organizations: 5},
{id: 2, name: "Test2", organizations: 6}
];
const mergeDuplicates= (field, uniqueField) => (source = [], value)=> {
const target = source.find( item => item[uniqueField] == value[uniqueField] );
if(target) target[field].push( value[field] );
else source.push({...value, [field]: [ value[field] ] });
return source;
}
const mergeOrganaizationsById = mergeDuplicates('organizations','id')
const result = array.reduce(mergeOrganaizationsById, [])
console.log(result)
You'll want to reduce.
array.reduce((acc, cur) => {
const i = acc.findIndex(a => a.id === cur.id && a.name === cur.name);
if (i === -1) return [...acc, {...cur, organizations: [cur.organizations]}];
return [...acc.slice(0, i), {...cur, organizations: [...acc[i].organizations, cur.organizations]}, ...acc.slice(i +1)];
}, []);
You can achieve the output using forEach by grouping based on name and then pushing the necessary fields into the output array.
const array = [
{ id: 1, name: "Test1", organizations: 1 },
{ id: 1, name: "Test1", organizations: 2 },
{ id: 1, name: "Test1", organizations: 3 },
{ id: 2, name: "Test2", organizations: 4 },
{ id: 2, name: "Test2", organizations: 5 },
{ id: 2, name: "Test2", organizations: 6 }
];
const current = Object.create(null);
const finalArr = [];
array.forEach(function (o) {
if (!current[o.name]) {
current[o.name] = [];
finalArr.push({ id: o.id, name: o.name, organizations: current[o.name] });
}
current[o.name].push(o.organizations);
});
console.log(finalArr);
.as-console-wrapper { max-height: 100% !important; top: 0; }
Another one solution in kind of ES6 style
const array= [{id: 1, name: "Test1", organizations: 1},{id: 1, name: "Test1", organizations: 2},{id: 1, name: "Test1", organizations: 3},{id: 2, name: "Test2", organizations: 4},{id: 2, name: "Test2", organizations: 5},{id: 2, name: "Test2", organizations: 6}];
const result = Object.values(array.reduce((acc, { id, name, organizations }) => {
const hash = `${id}-${name}`;
acc[hash] = acc[hash]
? { ...acc[hash], organizations: [...acc[hash].organizations, organizations] }
: { id, name, organizations: [organizations] };
return acc;
}, {}));
console.log(result);
.as-console-wrapper { max-height: 100% !important; top: 0; }
I think it may be the easiest way to tackle this problem, only using the forEach and basic arrays' method.
I hope I answered your question.
const array = [
{ id: 1, name: "Test1", organizations: 1 },
{ id: 1, name: "Test1", organizations: 2 },
{ id: 1, name: "Test1", organizations: 3 },
{ id: 2, name: "Test2", organizations: 4 },
{ id: 2, name: "Test2", organizations: 5 },
{ id: 2, name: "Test2", organizations: 6 }
];
const newArr = [];
// for keeping track for added item
const addedItems = [];
// for keeping track of added item idx
let addedItemIdx = 0;
array.forEach((item) => {
if (!addedItems.includes(item.id)) {
let tempOrg = item.organizations;
newArr.push({ ...item, organizations: [tempOrg] });
addedItems.push(item.id);
addedItemIdx++;
} else {
newArr[addedItemIdx - 1].organizations.push(item.organizations);
}
});
console.log(newArr);
What you are looking for is called a hashmap. You can read about them but the basic idea is that you make a key,value pair and access to the data with keys is very efficient(O(1) amortized). So here is one way to solve this problem in python. I am sure you can use it to solve it in your language.
array= [
{"id": 1, "name": "Test1", "organizations": 1},
{"id": 1, "name": "Test1", "organizations": 2},
{"id": 1, "name": "Test1", "organizations": 3},
{"id": 2, "name": "Test2", "organizations": 4},
{"id": 2, "name": "Test2", "organizations": 5},
{"id": 2, "name": "Test2", "organizations": 6}
]
# Initilize a hashmap
hash_map = {}
# Loop over all the items in array and create the hashmap
for item in array:
# key will be id and name as both are needed to group the organizations
# We have use comma to separate them as we assume that name or id cannot have comma
key = str(item["id"])+","+item["name"]
# IF key is already present then add the new organizations id to it
if key in hash_map:
hash_map[key].append(item["organizations"])
# Else make a new list with the current organizations id
else:
hash_map[key] = [item["organizations"]]
# Create the expected array
expected_array = []
for key,value in hash_map.items():
# Get the id and name by spliting the key that we created
idx,name = key.split(",")
expected_array.append({"id":idx,"name":name,"organizations":value})
print(expected_array)
const array = [
{ id: 1, name: "Test1", organizations: 1 },
{ id: 1, name: "Test1", organizations: 2 },
{ id: 1, name: "Test1", organizations: 3 },
{ id: 2, name: "Test2", organizations: 4 },
{ id: 2, name: "Test2", organizations: 5 },
{ id: 2, name: "Test2", organizations: 6 }
];
const result=array.reduce((acc,curr)=>{
const id=curr.id;
const {organizations}=curr;
const findIndex=acc.findIndex(item=> item.id===curr.id)
if(findIndex===-1){
acc.push({...curr,organizations:[organizations]});
} else {
acc[findIndex].organizations.push(curr.organizations)
}
return acc;
},[]);
console.log(result);
.as-console-wrapper { max-height: 100% !important; top: 0; }
This should work
const array = [{
id: 1,
name: "Test1",
organizations: 1
},
{
id: 1,
name: "Test1",
organizations: 2
},
{
id: 1,
name: "Test1",
organizations: 3
},
{
id: 2,
name: "Test2",
organizations: 4
},
{
id: 2,
name: "Test2",
organizations: 5
},
{
id: 2,
name: "Test2",
organizations: 6
}
];
const reducedArray = array.reduce((resultArray, arrayElement) => {
const elementIndex = resultArray.findIndex(element => element.id === arrayElement.id);
if (elementIndex !== -1) {
resultArray[elementIndex].organizations.push(arrayElement.organizations)
} else {
resultArray.push({
...arrayElement,
organizations: [arrayElement.organizations],
});
}
return resultArray;
}, []);
console.log(reducedArray)
const array = [{
id: 1,
name: "Test1",
organizations: 1
},
{
id: 1,
name: "Test1",
organizations: 2
},
{
id: 1,
name: "Test1",
organizations: 3
},
{
id: 2,
name: "Test2",
organizations: 4
},
{
id: 2,
name: "Test2",
organizations: 5
},
{
id: 2,
name: "Test2",
organizations: 6
}
];
const formattedData = array.reduce((result, {
id,
name,
organizations
}) => {
let filteredRow = result.find(row => row.id === id && row.name === name);
const org = filteredRow ? filteredRow.organizations : [];
org.push(organizations);
filteredRow = {
id,
name,
organizations: org
};
if (org.length === 1) result.push(filteredRow);
return result;
}, [])
console.log(formattedData)
in my current angular project I have to change a JSON array so that it can be displayed in a tree. So that the tree can output the object, a nested array must be packed in an object.
Expected form / output:
this.nodes = [
{
id: 1,
name: 'root1',
children: [
{ id: 2, name: 'child1' },
{ id: 3, name: 'child2' }
]
}, ....
My current form:
[{
id: 1,
name: 'root1',
name2: [{
id: 2,
name: 'child1'
},
{
id: 3,
name: 'child2',
name3: [{
id: 3,
name: 'child2'
}],
},
]
}], ...
How can I cange my 'name2' or 'name3' to children?
I've got this fat one liner:
const rename = (array) => array.map(item => Object.fromEntries(Object.entries(item).map(([k, v]) => k.match(/name\d+/) ? ['children', rename(v)] : [k, v])));
const nodes = [{
id: 1,
name: 'root1',
name2: [
{
id: 2,
name: 'child1'
},
{
id: 3,
name: 'child2',
name3: [
{
id: 3,
name: 'child2'
}
],
},
]
}];
const rename = (array) => array.map(item => Object.fromEntries(Object.entries(item).map(([k, v]) => k.match(/name\d+/) ? ['children', rename(v)] : [k, v])));
console.log(JSON.stringify(rename(nodes), null, 4));
// [
// {
// "id": 1,
// "name": "root1",
// "children": [
// {
// "id": 2,
// "name": "child1"
// },
// {
// "id": 3,
// "name": "child2",
// "children": [
// {
// "id": 3,
// "name": "child2"
// }
// ]
// }
// ]
// }
// ]
I want to get the count of Items in array A that are in B and return an array C that contains the count elements.
array A is:
arrA = [{id:1,name:"Nairobi"},{id:2,name:"New Delhi"},{id:3,name:"Singapore"},{id:4,name:"London"}]
array B is:
arrB = [{id:1,id_fk:1,name:"Steve"},{id:2,id_fk:1,name:"John"},{id:3,id_fk:2,name:"Stella"},{id:4,id_fk:3,name:"Kemi"},{id:5,id_fk:3,name:"Kelly"},{id:6,id_fk:4,name:"James"},{id:7,id_fk:4,name:"Marley"},{id:8,id_fk:4,name:"Oliver"}]
Using id_fk in array B as a "foreign key" for id in array A, the expected output is
[2,1,2,3]
My implementation code is
for (let arrayA of arrA){
let count = arrB.filter(a =>
{return a.id_fk === arrayA.id}).length;
}
You could take a Map and get the id as keys in the wanted order and reduce the second array for counting items with id_fk. As result take an array of the values of the map.
This approach uses a single loop for getting the id as keys and another loop for counting.
var arrA = [{ id: 1, name: "Nairobi" }, { id: 2, name: "New Delhi" }, { id: 3, name: "Singapore" }, { id: 4, name: "London" }],
arrB = [{ id: 1, id_fk: 1, name: "Steve" }, { id: 2, id_fk: 1, name: "John" }, { id: 3, id_fk: 2, name: "Stella" }, { id: 4, id_fk: 3, name: "Kemi" }, { id: 5, id_fk: 3, name: "Kelly" }, { id: 6, id_fk: 4, name: "James" }, { id: 7, id_fk: 4, name: "Marley" }, { id: 8, id_fk: 4, name: "Oliver" }],
result = Array.from(arrB
.reduce(
(m, { id_fk }) => m.set(id_fk, m.get(id_fk) + 1),
new Map(arrA.map(({ id }) => [id, 0]))
)
.values()
);
console.log(result);
.as-console-wrapper { max-height: 100% !important; top: 0; }
A result with a hash table and new objects with a count property.
var arrA = [{ id: 1, name: "Nairobi" }, { id: 2, name: "New Delhi" }, { id: 3, name: "Singapore" }, { id: 4, name: "London" }],
arrB = [{ id: 1, id_fk: 1, name: "Steve" }, { id: 2, id_fk: 1, name: "John" }, { id: 3, id_fk: 2, name: "Stella" }, { id: 4, id_fk: 3, name: "Kemi" }, { id: 5, id_fk: 3, name: "Kelly" }, { id: 6, id_fk: 4, name: "James" }, { id: 7, id_fk: 4, name: "Marley" }, { id: 8, id_fk: 4, name: "Oliver" }],
hash = {},
result = arrA.map(o => Object.assign(hash[o.id] = {}, o, { count: 0 }));
arrB.forEach(({ id_fk }) => hash[id_fk].count++);
console.log(result);
.as-console-wrapper { max-height: 100% !important; top: 0; }
I would do it like this. https://jsfiddle.net/6egs7uLy/
let counts = [];
arrA.forEach((item, index) => {
let count = 0;
arrB.forEach((item2, index) => {
if(item['id'] === item2['id_fk']) {
count++;
}
})
counts.push(count);
count = 0;
})
I have static array constant of objects something similar to below.
export const EMPLOYEES = [
{
id: 2,
name: ‘John’,
},
{
id: 3,
name: ‘Doe’,
},
{
id: 4,
name: ‘Bull’,
},
{
id: 5,
name: ‘Scott’,
},
];
Now I need to add the last element only based on if some condition is true. Some this like if isAmerican() is true.
Can somebody help me here how to add element based on the condition? Thanks.
You can do it using spread operator:
export const EMPLOYEES = [
{
id: 2,
name: "John",
},
{
id: 3,
name: "Doe",
},
{
id: 4,
name: "Bull",
},
{
id: 5,
name: "Scott",
},
... isAmerican() ? [{ id: 6, name: "Jemmy"}] : []
];
You should never modify (or try to modify) a constant. I can see two ways you can do this:
Create a pure function to return a new constant with the new object added to the array
Use a spread operator in the definition of the constant
Option 1: Pure function
function makeNewArray(array, objectToAppend, isAmerican) {
return isAmerican ? [...array, objectToAppend] : array
}
const EMPLOYEES = [
{
id: 2,
name: "John",
},
{
id: 3,
name: "Doe",
},
{
id: 4,
name: "Bull",
},
{
id: 5,
name: "Scott",
}
];
const arrayWithAmerican = makeNewArray(EMPLOYEES, { id: 6, name: "American Frank"}, true);
const arrayWithoutAmerican = makeNewArray(EMPLOYEES, { id: 6, name: "Not American Frank"}, false);
console.log(arrayWithAmerican);
console.log(arrayWithoutAmerican);
Option 2: Spread operator
function isAmerican(){
// generic code here.
return true;
}
const EMPLOYEES = [
{
id: 2,
name: "John",
},
{
id: 3,
name: "Doe",
},
{
id: 4,
name: "Bull",
},
{
id: 5,
name: "Scott",
},
... isAmerican() ? [{ id: 6, name: "American Frank"}] : []
];
If the condition will be fulfilled, simply push an object to your EMPLOYEES array:
let isAmerican = true;
const EMPLOYEES = [
{
id: 2,
name: "John",
},
{
id: 3,
name: "Doe",
},
{
id: 4,
name: "Bull",
},
{
id: 5,
name: "Scott",
},
];
if(isAmerican) {
EMPLOYEES.push({
id: 6,
name: "Frank"
})
}
console.log(EMPLOYEES)
Fiddle: https://jsfiddle.net/rqx35pLz/