Check if value exists in nested array - javascript

I am trying to check if a value is present in a nested array. This is what the data I am working with looks like:
[
{
name: 'bob',
occupation: ['Teacher', 'Store Owner'],
},
{
name: 'grace',
occupation: ['Doctor'],
},
]
I am trying to see if the occupation value already exists. This is my current code:
const occupationExists = (value) => users.some((user) => user.occupation === value);
I understand that this doesn't work because it isn't accessing the values in the array but how do I go about it? Any help would be appreciated.

You need to check occupation as well with Array#includes.
const occupationExists = value => users.some(user =>
user.occupation.includes(value)
);

This should do the trick, it returns true/false depending on whether the occupation exists or not.
let users = [
{
name: 'bob',
occupation: ['Teacher', 'Store Owner'],
},
{
name: 'grace',
occupation: ['Doctor'],
},
]
const occupationExists = (value) => {
let res = users.filter((user) =>
user.occupation.indexOf(value) != -1
)
return res.length > 0
}
let value = 'Doctor'
console.log(occupationExists(value))

Here is the issue with user.occupation === value: user.occupation is an array of string while value is a string, hence you cannot compare the two. You can use Array#includes() as stated by #NinaScholz or you can use another (inner) Array#some() and within it you can compare string to string: job === value.
const users = [{name: 'bob',occupation: ['Teacher', 'Store Owner']}, {name: 'grace',occupation: ['Doctor']}];
//const occupationExists = value => users.some(user => user.occupation.includes(value)); //best answer
//Alternative answer
const occupationExists = value => users.some(
user => user.occupation.some(job => job === value)
);
console.log( occupationExists('Teacher') );
console.log( occupationExists('Developer') );

let aoo = [
{
name: 'bob',
occupation: ['Teacher', 'Store Owner'],
},
{
name: 'grace',
occupation: ['Doctor', 'Store Owner'],
},
]
let fullOccupation = []
aoo.map(obj => {
obj.occupation.map(occ => {
const check = fullOccupation.includes(occ)
console.log(occ)
if(!check)
{
fullOccupation.push(occ)
}else{
alert(occ)
}
})
})

Related

Using indexOf in order to filt an array - ( Next.js app with typescript )

I have this array in my next.js app
arr1
[
{
identifier: "60a17722225f2918c445fd19",
name: "Ben Awad",
_id: "60c94480b8d43c28d0a6eb73
},
{
identifier: "60a455d11fa62a1510b408f8",
name: "dev ed"
_id: "60bf62cede309f1a30fe88ab"
}
]
And i have this another big array
arr2
[
{
name: "Ben Awad",
_id: "60a17722225f2918c445fd19
},
{
name: "dev ed",
_id: "60a455d11fa62a1510b408f8"
},
{
name: "Katlyn",
_id: "60a52500ce96f30c14fdaff9"
},
{
name: "Mike",
_id: "60c95deeb8d43c28d0a6eb74"
},
{
name: "Kassandra",
_id: "60c960ddb8d43c28d0a6eb7a"
}
]
I want a new array who should have all users except for those who have similar ids with arr1
So this is the logic i did (Notice that arr1 and arr2 will change constantly)
Me = arr1
AllUsers = arr2
const LookFriends =
Me &&
AllUsers.filter(({ _id }) => {
return Me.friends.indexOf(_id) === -1;
});
console.log(LookFriends);
The output should be Katlyn, Mike and Kassandra, but the console.log says...
[
{
name: "Ben Awad",
_id: "60a17722225f2918c445fd19
},
{
name: "dev ed",
_id: "60a455d11fa62a1510b408f8"
},
{
name: "Katlyn",
_id: "60a52500ce96f30c14fdaff9"
},
{
name: "Mike",
_id: "60c95deeb8d43c28d0a6eb74"
},
{
name: "Kassandra",
_id: "60c960ddb8d43c28d0a6eb7a"
}
]
I'm really having a hard time trying to filter an array based on another array, what can i do ?
You need to use 'findIndex' in this case, then compare the _id field itself:
const LookFriends =
Me &&
AllUsers.filter(({ _id }) => {
return Me.friends.findIndex(friend => friend._id === _id) === -1;
});
If you use "indexOf", it will compare the entire object to just that _id value.
You can extract the identifiers from the first array and filter the second array if the element doesn't match any id in our object or our Set
// with an object
const ids = {}
arr1.forEach(user => {
ids[user.identifier] = true
})
const filtered = arr2.filter(user => !ids[user._id])
// or with a Set
const ids = new Set(arr1.map(user => user.identifier))
const filtered = arr2.filter(user => !ids.has(user._id))
Please have a try with this code.
Me &&
AllUsers.filter(({ _id }) => {
let bExist = false
Me.friends.map( (friend) => {
if ( friend._id === _id )
bExist = true
})
return bExist
});
Let me know if it works or not.

How to update the value into a nested array of objects if value for specific key is same?

let data = [
{"name":"Dhanush","createdAt":"2021/01/13 16:57:53","songs":[]},
{"name":"Dharma","createdAt":"2021/01/13 17:02:47","songs":[]},
{"name":"Sachin","createdAt":"2021/01/13 17:30:45","songs":[]}
]
let name = "Dhanush"
let song = {
'id':1,
'duration': '5 mins',
'name': 'Bingo'
}
Here I need to loop the data array and check if data.name === name , if it s true I need to push the song object to the songs array inside the data.
this means
data = data.map(val => val.name === name ? val.songs = [...val.songs,song] : val.songs)
I tried like this. but it doesn't work.
Your help is much appreciated.
Thanks
You are not returning val when using map method.
let data = [
{ name: 'Dhanush', createdAt: '2021/01/13 16:57:53', songs: [] },
{ name: 'Dharma', createdAt: '2021/01/13 17:02:47', songs: [] },
{ name: 'Sachin', createdAt: '2021/01/13 17:30:45', songs: [] },
];
const name = 'Dhanush';
const song = {
id: 1,
duration: '5 mins',
name: 'Bingo',
};
data = data.map(
(val) => (
val.name === name ? (val.songs = [...val.songs, song]) : val.songs, val
)
);
console.log(data);

How to get index of a dynamic JSON object in an array using javascript

I want to define a function to find index of a JSON object in an array. The JSON object is dynamic.Here object keys/attributes are not constant in JSON.
How to find index of matched object (all key& values) in array?
For example:
let obj={name:'Bill', phone:'8562456871', email:'bill#email.com'};
let arrayObj=[{street:'wardcircle', city:'Brentwood'},{name:'wan',email:'wan#test.com' },{name:'bill', phone:'8562456871', email:'bill#email.com'}];
let indx=getIndex(obj,arrayObj); // expected result is 2
I have defined function like this but it is not working for all dynamic attribute & values:
getIndex(obj,arrayObj){
Object.keys(obj),forEach((key,index)=>{
return arrayObject.findIndex(x=>x[key]==obj[key]);// Here I am unable to add AND condition for other key& values.
});
}
Put the .findIndex first, and inside it, check that .every one of the Object.keys matches.
Note that your current object has name: 'Bill' but the array has name: 'bill' - the values should match, case sensitivity matters (unless you want to ignore it, in which case you'll have to call toLowerCase() on both values first).
let obj = {
name: 'bill',
phone: '8562456871',
email: 'bill#email.com'
};
let arrayObj = [{
street: 'wardcircle',
city: 'Brentwood'
}, {
name: 'wan',
email: 'wan#test.com'
}, {
name: 'bill',
phone: '8562456871',
email: 'bill#email.com'
}];
const getIndex = (findObj, array) => (
array.findIndex(obj => (
Object.entries(findObj).every(([key, val]) => obj[key] === val)
))
);
console.log(getIndex(obj, arrayObj));
If you also want to make sure that the found object doesn't have any properties not in the findObj, check that the number of keys on both are the same too:
let obj = {
name: 'bill',
phone: '8562456871',
email: 'bill#email.com'
};
let arrayObj = [{
street: 'wardcircle',
city: 'Brentwood'
}, {
name: 'wan',
email: 'wan#test.com'
}, {
name: 'bill',
phone: '8562456871',
email: 'bill#email.com'
}];
const getIndex = (findObj, array) => (
array.findIndex(obj => (
Object.keys(obj).length === Object.keys(findObj).length &&
Object.entries(findObj).every(([key, val]) => obj[key] === val)
))
);
console.log(getIndex(obj, arrayObj));

Joining two arrays of JSON objects like an SQL join using functional programming

Consider, I have the following two arrays of objects:
const existingAndArchivedBookings =
[
{"booking_id":-2},
{"booking_id":-1},
{"booking_id":999}
]
const newAndExistingBookings =
[
{bookingId:-2, name: "name1"},
{bookingId:-3, name: "name1"},
{bookingId:-1, name: "namex"}
]
What I want to do is determine which of the bookings in the second array are new and which are existing. Any bookingId that is in both arrays is existing. Any bookingID that is in the second array but not the first is new. So, the result of the solution should be an array as follows:
[ { bookingId: -2, existing: true, name: 'name1' },
{ bookingId: -3, existing: false, name: 'name1' },
{ bookingId: -1, existing: true, name: 'namex' } ]
I have a solution (which I'll post as an answer), but I think there's probably a more efficient way of doing it. Good luck.
If you want a non-R answer: you can use a simple map to iterate over the data, compare the booking ids in both arrays (with some), and return a new array of objects.
const existingAndArchivedBookings = [{booking_id:-2},{booking_id:-1},{booking_id:999}];
const newAndExistingBookings = [{bookingId:-2, name: "name1"},{bookingId:-3, name: "name1"},{bookingId:-1, name: "namex"}];
function testBookings(arr1, arr2) {
return arr2.map(({ bookingId, name }) => {
const existing = arr1.some(obj => obj.booking_id === bookingId);
return { bookingId, existing, name };
});
}
const out = testBookings(existingAndArchivedBookings, newAndExistingBookings);
console.log(out);
You can greatly simplify it using Array.prototype.reduce to form the result of the comparisons between the 2 arrays and Array.prototype.findIndex to test whether the object in the second array is present in the first array:
const existingAndArchivedBookings =
[
{"booking_id":-2},
{"booking_id":-1},
{"booking_id":999}
]
const newAndExistingBookings =
[
{bookingId:-2, name: "name1"},
{bookingId:-3, name: "name1"},
{bookingId:-1, name: "namex"}
]
const res = newAndExistingBookings.reduce((acc, ele) => {
const idx = existingAndArchivedBookings.findIndex(b => b.booking_id === ele.bookingId);
let existing = false;
if(idx >=0 ){
existing = true;
}
return acc.concat({bookingId : `${ele.bookingId}`, existing: `${existing}`, name: `${ele.name}`});
}, []);
console.log(res);
Here's what I came up with, which seems a bit long winded
const R = require('ramda')
const existingAndArchivedBookings = [{"booking_id":-2},{"booking_id":-1},{"booking_id":999}]
const newAndExistingBookings = [{bookingId:-2, name: "name1"}, {bookingId:-3, name: "name1"}, {bookingId:-1, name: "namex"}]
const existingAndArchivedKeys = existingAndArchivedBookings.map(value => value.booking_id)
const newAndExistingKeys = newAndExistingBookings.map(value => value.bookingId)
const existingKeys = existingAndArchivedKeys.filter(key => newAndExistingKeys.includes(key))
const newKeys = newAndExistingKeys.filter(key => !existingAndArchivedKeys.includes(key))
const existingBookingIds = existingKeys.map(key => {
return {bookingId: key, existing: true}
})
const newBookingIds = newKeys.map(key => {
return {bookingId: key, existing: false}
})
const allArray = R.concat(newAndExistingBookings, R.concat(existingBookingIds, newBookingIds))
console.log(R.values(R.reduceBy(R.mergeLeft, {}, R.prop('bookingId'), allArray)))

Find duplicate values by key from array of objects in Javascript

I know this question was answered before multiple times.
but i didn't find any solution that helped me out.
I got an array of objects with a Name property. I only want to get the objects with the same name.
How my Array looks like:
[
{
Name: 'test',
coolProperty: 'yeahCool1'
},
{
Name: 'test1',
coolProperty: 'yeahCool2'
},
{
Name: 'test2',
coolProperty: 'yeahCool3'
},
{
Name: 'test3',
coolProperty: 'yeahCool4'
},
{
Name: 'test',
coolProperty: 'yeahCool5'
}
]
so I only want to get:
[
{
Name: 'test',
coolProperty: 'yeahCool1'
},
{
Name: 'test',
coolProperty: 'yeahCool5'
}
]
I hope someone can help me out :)
For an O(N) solution, first reduce the array into an object that counts the number of occurrences of each name, and then filter the input by the occurrence count being 2:
const arr = [
{
Name: 'test',
coolProperty: 'yeahCool1'
},
{
Name: 'test1',
coolProperty: 'yeahCool2'
},
{
Name: 'test2',
coolProperty: 'yeahCool3'
},
{
Name: 'test3',
coolProperty: 'yeahCool4'
},
{
Name: 'test',
coolProperty: 'yeahCool5'
}
];
const counts = arr.reduce((a, { Name }) => {
a[Name] = (a[Name] || 0) + 1;
return a;
}, {});
console.log(arr.filter(({ Name }) => counts[Name] === 2));
You could use reduce() and filter() method to get the required result.
Using filter() method you need to check if length is greater than 2 then need it will be push in new array inside of reduce() method
DEMO
const arr =[{"Name":"test","coolProperty":"yeahCool1"},{"Name":"test1","coolProperty":"yeahCool2"},{"Name":"test2","coolProperty":"yeahCool3"},{"Name":"test3","coolProperty":"yeahCool4"},{"Name":"test","coolProperty":"yeahCool5"}];
let getCount = (name)=>{
return arr.filter(o => o.Name == name).length;
}
console.log(arr.reduce((r,item) => {
let len = getCount(item.Name);
return r.concat(len>1?item:[]);
}, []));
I see that you have already got an answer. So I thought of adding another way using map.
var counts = {};
var repeats = {};
arr.map(i => {
counts[i['Name']] = (counts[i['Name']] || []);
counts[i['Name']].push(i);
if (counts[i['Name']].length > 1) {
repeats[i['Name']] = counts[i['Name']];
}
});
console.log(repeats);
Not the best solution considering the performance. Just wanted to add an alternative method.
Hope it helps!!

Categories

Resources