how to select parent property in object javascript - javascript

how to put the user hobby property (in line 2) into the friend hobby property (in line 6)
const user = {
hobby: 'sports',
friends: [{
name: 'jhon',
age: '22',
get hobby () {
// how to return user hobby here?
}
}]
}

const user = {
hobby: 'sports',
friends: [{
name: 'jhon',
age: '22',
get hobby () {
return user.hobby
}
}]
}
user.friends[0].hobby // 'sports'
Or if you have a list of those objects and you want to add the getter to them:
const users = [
{
hobby: 'sports',
friends: [{ name: 'jhon', age: 22 }]
}, {
hobby: 'cooking',
friends: [{ name: 'jane', age: 23 }]
}
]
for (const u of users)
Object.defineProperty(u.friends[0], 'hobby', {
get() {
return u.hobby
}
})
users[0].friends[0].hobby // 'sports'
users[1].friends[0].hobby // 'cooking'

Related

Merge array of objects preserving some key-values php

Consider the following two arrays:
[
{
id: jhz,
name: 'John',
eyes: 'Green',
description: 'Cool guy',
},
{
id: mbe,
name: 'Mary',
brand: 'M&B',
text: 'Something',
}
]
[
{
id: jhz,
name: 'John',
eyes: '',
},
{
id: mbe,
name: 'Mary',
},
{
id: 'beh',
name: 'Bernard',
}
]
First array may have any kind of key value pairs, but it will always have the key id and name. I want to merge the two arrays by taking id and name into account and preserving them, while merging everything else and replacing them with data from the first array if any keys duplicate.
Also tricky part - the merged array needs to follow the order of the second array.
So in this example the result I'm looking for is:
[
{
id: jhz,
name: 'John',
eyes: 'Green',
description: 'Cool guy',
},
{
id: mbe,
name: 'Mary',
brand: 'M&B',
text: 'Something',
},
{
id: 'beh',
name: 'Bernard',
}
]
you can do something like this using Array.map
const data1 = [{
id: 'jhz',
name: 'John',
eyes: 'Green',
description: 'Cool guy',
},
{
id: 'mbe',
name: 'Mary',
brand: 'M&B',
text: 'Something',
}
]
const data2 = [{
id: 'jhz',
name: 'John',
eyes: '',
},
{
id: 'mbe',
name: 'Mary',
},
{
id: 'beh',
name: 'Bernard',
}
]
const result = data2.map(d => ({...d, ...(data1.find(d1 => d1.id === d.id && d1.name === d.name) || {})}))
console.log(result)

How to remove a simple specific key value pair from all objects and add to one specific object inside an array

I want to add a key and value(i.e. age:15) to an object which has name as email and remove it(age) from other objects for the below array of object.
[
{
name: 'test',
lname: 'last',
age: 5
},
{
name: 'test1',
lname: 'last1',
age: 15
},
{
name: 'email',
lname: 'last',
},
]
i.e. I want the below output.
[
{
name: 'test',
lname: 'last'
},
{
name: 'test1',
lname: 'last1'
},
{
name: 'email',
lname: 'last',
age: 15
},
]
Thanks
What you can do here is find the index of the object that has name as "email". Once you find the object, add the desired age value as a new property called age. Finally, you can use filter to filter the items that doesn't have name as "email" and delete the age property.
var data = [ { name: 'test', lname: 'last', age: 5 }, { name: 'test1', lname: 'last1', age: 15 }, { name: 'email', lname: 'last', }, ]
function myFunction(age) {
let indexOfEmail = data.findIndex(element => element.name == "email")
if (indexOfEmail > -1) {
data[indexOfEmail].age = age
data.filter(element => element.name !== "email").map(sub => delete sub['age'])
}
}
myFunction(15)
console.log(data)
You can do it by using map method, like this:
const data = [
{
name: 'test',
lname: 'last',
age: 5
},
{
name: 'test1',
lname: 'last1',
age: 15
},
{
name: 'email',
lname: 'last',
},
];
const newData = data.map(({age, ...rest})=> rest.name == 'email' ? {...rest, age: 15} : rest)
console.log(newData);
You can do like this:
const items = [
{
name: 'test',
lname: 'last',
age: 5
},
{
name: 'test1',
lname: 'last1',
age: 15
},
{
name: 'email',
lname: 'last',
},
];
const newItems = items.filter((item) => {
if (item.name.includes("email")) {
return (item.age = 15);
}
if (JSON.stringify(items).includes("email")) {
delete item.age;
}
return item;
});
console.log(newItems);

How to compare the sameness of object entries of 2 arrays and how to create a merger of both objects with custom properties of the found same object?

I am trying to compare 2 objects by their property and the values Strictly using forloop. If the value of the "name" or another property matches up with each other, I want to push the property and value to value3.
Once value3 is logged, I want the response like this:
{
name: 'dog',
surname: 'good',
skills: 'programming',
age: '22'
},
{
name: 'cat',
surname: 'soft',
skills: 'engineer'
age: '12'
},
{
name: 'elephant',
surname: 'big',
skills: 'programming'
age: '23'
}
Here is the code:
var values1 = [
{
name: 'dog',
surname: 'good',
skills: 'programming'
},
{
name: 'cat',
surname: 'soft',
skills: 'engineer'
},
{
name: 'elephant',
surname: 'big',
skills: 'programming'
}
]
var values2 = [
{
name: 'cat',
food: 'fish',
age: '12'
},
{
name: 'elephant',
food: 'leafs',
age: '13'
},
{
lastname: 'dog',
food: 'treats',
age: '22'
}
]
// push into this empty object array
var values3 = [{}]
console.log(values3)
The most generic approach which fulfills all of the OP's requirements should be based on Array.prototype.reduce. Its advantage comes with utilizing the additionally passed optional initial value as kind of configurable collector/accumulator object which will carry all the needed additional information / functions / result. Thus one can provide a reusable function with a customizable context/environment which one can adapt to ones needs.
var values1 = [{
name: 'dog',
surname: 'good',
skills: 'programming',
}, {
name: 'cat',
surname: 'soft',
skills: 'engineer',
}, {
name: 'elephant',
surname: 'big',
skills: 'programming',
}];
var values2 = [{
name: 'cat',
food: 'fish',
age: '12'
}, {
name: 'elephant',
food: 'leafs',
age: '13'
}, {
lastname: 'dog',
food: 'treats',
age: '22'
}];
function mergeItemsOfSameEntry(collector, item) {
const {
getSameEntryValue,
getMergeSubType,
comparisonItems,
result
} = collector;
const itemValue = getSameEntryValue(item);
const comparisonItem = comparisonItems
.find(cItem => getSameEntryValue(cItem) === itemValue);
if (comparisonItem !== null) {
result.push({
...item,
...getMergeSubType(comparisonItem),
});
}
return collector;
}
const values3 = values1.reduce(mergeItemsOfSameEntry, {
getSameEntryValue: item => item.name ?? item.lastname,
getMergeSubType: ({ age }) => ({ age }),
comparisonItems: values2,
result: [],
}).result;
console.log({ values3 });
.as-console-wrapper { min-height: 100%!important; top: 0; }
If you just want the key and value pair, you can do something like this:
var values1 = [
{
name: 'dog',
surname: 'good',
skills: 'programming'
},
{
name: 'cat',
surname: 'soft',
skills: 'engineer'
},
{
name: 'elephant',
surname: 'big',
skills: 'programming'
}
]
var values2 = [
{
name: 'cat',
food: 'fish',
age: '12'
},
{
name: 'elephant',
food: 'leafs',
age: '13'
},
{
lastname: 'dog',
food: 'treats',
age: '22'
}
]
// push into this empty object array
var values3 = [];
values1.forEach(eachValue1Obj => {
const keys = Object.keys(eachValue1Obj);
keys.forEach(eachKey => {
values2.forEach(eachValue2Obj => {
if (
eachValue1Obj[eachKey] &&
eachValue2Obj[eachKey] &&
eachValue1Obj[eachKey] === eachValue2Obj[eachKey]
) {
const x = {
key: eachKey,
value: eachValue1Obj[eachKey]
};
values3.push(x)
}
})
})
})
console.log('Values 3 Array ==>', values3);

How to retrieve inner array elements by matching key value in React JS

I have been trying to retrieve inner elements using ReactJs. If my input is country=NZ then I am expecting 4 results, it should consider the inner array also, however when I used jsonQuery it is not able to go to the inner array and fetching only 3 results, and it's not going inside friends1. Is there any way we can fetch inner array elements as well?
var result1 = jsonQuery('grouped_people[**][*country=NZ]', {data: data1}).value;
console.log(result1);
console.log("Array1");
var data1 = {
grouped_people: {
'friends': [
{ name: 'Steve', country: 'NZ' },
{ name: 'Jane', country: 'US' },
{ name: 'Mike', country: 'AU' },
{ name: 'Mary', country: 'NZ' },
],
'enemies': [
{ name: 'Steve', country: 'NZ' },
{
'friends1': [
{ name: 'Evil Steve', country: 'India' },
{ name: 'Betty', country: 'NZ' },
]
}]
}
}
You should be able to optimise it as per your convenience.
var data1 = {
grouped_people: {
'friends': [
{ name: 'Steve', country: 'NZ' },
{ name: 'Jane', country: 'US' },
{ name: 'Mike', country: 'AU' },
{ name: 'Mary', country: 'NZ' },
],
'enemies': [
{ name: 'Steve', country: 'NZ' },
{
'friends1': [
{ name: 'Evil Steve', country: 'India' },
{ name: 'Betty', country: 'NZ' },
]
}]
}
}
const COUNTRY = "NZ";
const arr = [];
function getObject(obj) {
if (obj.country) {
if (obj.country === COUNTRY) {
arr.push(obj);
return;
}
} else {
Object.keys(obj).map(key => {
obj[key].map(item => {
getObject(item);
});
});
}
}
getObject(data1.grouped_people);
console.log(arr);
I used recursion to check (inside the check function ) whether the passed argument is an object. If so, then check for the key country and name and if they exist and the country value matches the inp then increment the result1 by 1 and if the keys don't exist, call the function on the values of the keys.
if the type is not object, then, get every element of the new object(which can only be an array) and call the function over it.
let inp = 'NZ';
var result1 = 0;
console.log(result1);
console.log("Array1");
var data1 = {
grouped_people: {
'friends': [
{ name: 'Steve', country: 'NZ' },
{ name: 'Jane', country: 'US' },
{ name: 'Mike', country: 'AU' },
{ name: 'Mary', country: 'NZ' },
],
'enemies': [
{ name: 'Steve', country: 'NZ' },
{
'friends1': [
{ name: 'Evil Steve', country: 'India' },
{ name: 'Betty', country: 'NZ' },
]
}]
}
}
function check(obj) {
if (!Array.isArray(obj)) {
let keys = Object.keys(obj);
if(keys.includes('country') && keys.includes('name')) {
if(obj['country'] == inp) {
result1 += 1
}
}else {
keys.map(key => {
check(obj[key])
})
}
}
else {
obj.map(ob => {
check(ob)
})
}
return result1;
}
let res = check(data1);
console.log(res);
If using jsonQuery is not absolutely necessary, you can spread out the objects that you want into a dataset and format it using filter.
let resultSet = [...data1.grouped_people.friends, data1.grouped_people.enemies[0], ...data1.grouped_people.enemies[1].friends1]
resultSet.filter(e => e.country == 'NZ')

Compare two arrays to get count of properties

I have two arrays that I would like to compare and provide a count of the items in the master list.
The master list might look like this:
{ name: 'Jon', age: 34 },
{ name: 'Steve', age: 33 },
{ name: 'Mark', age: 34 },
{ name: 'Jon', age: 35 }
The Filter list gets all possible names / ages from the database. Some might not have any entries. Each of these lists are getting pulled from an API individually. I will combine them into one array:
{ users:
[{ username: 'Jon' },
{ userName: 'Steve' },
{ username: 'Mark' },
{ username: 'Mike' }],
ages:
[{age: 33},
{age: 34},
{age: 35},
{age: 36}]
}
What I would like to do is be able to count how many of each name I have
Jon - 2, Steve - 1, Mark - 1, Mike - 0
33 - 1, 34 - 2, 35 - 1
Here is a generic approach. You provide the data and the field you want to count.
var data = [
{ name: 'Jon', age: 34 },
{ name: 'Steve', age: 33 },
{ name: 'Mark', age: 34 },
{ name: 'Jon', age: 35 }
];
function countUnique(items, property) {
return items.reduce(function(map, item) {
if (item.hasOwnProperty(property)) {
map[item[property]] = (map[item[property]] || 0) + 1;
}
return map;
}, {});
}
console.log(countUnique(data, 'name')); // Object {Jon: 2, Steve: 1, Mark: 1}
console.log(countUnique(data, 'age')); // Object {33: 1, 34: 2, 35: 1}
Filtering
If you want to filter a list of users by conditions, you can define an array of filter objects as seen below. When filtering a list of items, you usually will provide a predicate function to execute on the current item in the filter call. This function returns a boolean value which determines whether or not the item meets the conditions of the function.
var users = [
{ name: 'Jon', age: 34 },
{ name: 'Steve', age: 33 },
{ name: 'Mark', age: 34 },
{ name: 'Jon', age: 35 }
];
var filters = [{
name: 'users',
predicate : function(user) {
return [ 'Jon', 'Mark', 'Mike' ].indexOf(user.name) > -1;
}
}, {
name: 'ages',
predicate : function(user) {
return user.age >= 34 && user.age <= 36;
}
}];
print(filterFactory(users, getFiltersByName(filters, ['users', 'ages'])));
function getFiltersByName(filters, names) {
return filters.filter(function(filter) {
return names.indexOf(filter.name) > -1;
});
}
function filterFactory(items, filters) {
return items.filter(function(item) {
return filters.some(function(filter) {
try { return filter.predicate.call(undefined, item); }
catch (e) { throw new Error('predicate undefined for filter: ' + filter.name); }
});
});
}
function print(obj) {
document.body.innerHTML = JSON.stringify(obj, undefined, ' ');
}
body { font-family: monospace; white-space: pre }
Something like this would do. Here is a fiddle http://jsfiddle.net/5jkqv6k3/
var data = [
{ name: 'Jon', age: 34 },
{ name: 'Steve', age: 33 },
{ name: 'Mark', age: 34 },
{ name: 'Jon', age: 35 }
];
var key = function(obj) {
// Some unique object-dependent key
return obj.name; // Just an example
};
var dict = {};
for (var i = 0; i < data.length; i++) {
if (dict[key(data[i])])
dict[key(data[i])] = dict[key(data[i])] + 1;
else
dict[key(data[i])] = 1;
}
console.log(dict);
Using angularJs (because you're using it as you said) you can do this:
var countNamesList = {};
var countAgesList = {};
angular.forEach(masterList, function(value, index) {
countNamesList[masterList[index].name] =
(!angular.isUndefined(countNamesList[masterList[index].name])) ?
countNamesList[masterList[index].name] + 1 : 1;
countAgesList[masterList[index].age] =
(!angular.isUndefined(countAgesList[masterList[index].age])) ?
countAgesList[masterList[index].age] + 1 : 1;
});
console.log(countNamesList);
console.log(countAgesList);
JSFIDDLE
Mr. Polywhirl's answer is your best option on counting.
Now here's how you can filter:
var master = [
{ name: 'Jon', age: 34 },
{ name: 'Steve', age: 33 },
{ name: 'Mark', age: 34 },
{ name: 'Jon', age: 35 }
];
var filter = {
users: [
{ username: 'Jon' },
{ username: 'Mark' },
{ username: 'Mike' }
], ages: [
{ age: 34 },
{ age: 35 },
{ age: 36 }
]
};
function filterByNameAndAge(obj) {
return filter.users.some(function(user) {
return user.username === obj.name;
}) && filter.ages.some(function(age) {
return age.age === obj.age;
});
}
console.log(master.filter(filterByNameAndAge));
Currently it accepts only objects with matching name and age. Replace the && inside filterByNameAndAge by || if it should accept objects with matching name or age.

Categories