This question already has answers here:
Get all unique values in a JavaScript array (remove duplicates)
(91 answers)
Closed 4 years ago.
I need to loop through an array of objects and sum the total number of unique _id(s). Imagine a data structure that looks like this:
[
{ firstName: "John",
lastName: "Johnson",
_id: 23
},
{ firstName: "John",
lastName: "Johnson",
_id: 23
},
{ firstName: "Mary",
lastName: "Smith",
_id: 24
}
]
... for the above data set, my totalUniqueIDs should be 2.
If I were just looping through an array and getting the sum of "_id", I would do this:
let customersArray = docs.map(doc => doc._id);
let customersArrayLength = customersArray.length
console.log(customersArrayLength); // 3
This would of course give me 3 results.
How would I get just the sum of unique _id(s) in this situation? Do I first convert the array to a set, and then find the length or size?
Another option is using reduce to summarise the array into an object using the _id as the key. Use Object.values to convert back the object into an array.
var arr = [{"firstName":"John","lastName":"Johnson","_id":23},{"firstName":"John","lastName":"Johnson","_id":23},{"firstName":"Mary","lastName":"Smith","_id":24}]
var result = Object.values(arr.reduce((c, v) => Object.assign(c, {[v._id]:v}), {}));
console.log(result.length);
Another option is using new Set and size property
var arr = [{"firstName":"John","lastName":"Johnson","_id":23},{"firstName":"John","lastName":"Johnson","_id":23},{"firstName":"Mary","lastName":"Smith","_id":24}]
var result = new Set(arr.map(o => o._id)).size;
console.log(result);
you can use .map() to get an array of ids and use Set to dedupe it :
const data = [{
firstName: "John",
lastName: "Johnson",
_id: 23
},
{
firstName: "John",
lastName: "Johnson",
_id: 23
},
{
firstName: "Mary",
lastName: "Smith",
_id: 24
}
]
const result = [... new Set(data.map(({_id}) => _id))]
console.log(result.length)
Get all the _id from your array of object using map() and use Set to find unique _id and finally use size to get how many of ids are unique?
The Set object lets you store unique values of any type
The map() method creates a new array with the results of calling a provided function on every element in the calling array
var obj = [{
"firstName": "John",
"lastName": "Johnson",
"_id": 23
},
{
"firstName": "John",
"lastName": "Johnson",
"_id": 23
},
{
"firstName": "Mary",
"lastName": "Smith",
"_id": 24
}
];
function countUnique(iterable) {
return new Set(iterable).size;
}
finalArray = obj.map(function(obj) {
return obj._id;
});
console.log(countUnique(finalArray));
Related
I have a object which has some properties for one user, and I have array of objects which is returned from API.
My goal is to check which object of Array of objects has the same property as the one single initial object, and then it should return only part of it's properities.
I have tried to use .map on Array of objects but it seems not workig.
Below is the code example. I have also prepared codesandbox if You wish.
const user =
{
name: "jan",
lastName: "kowalski",
fullName: "jan kowalski",
car: "audi"
}
;
const usersAnimal = [
{
name: "jan",
lastName: "kowalski",
fullName: "jan kowalski",
animal: "cat",
animalSize: "small",
animalName: "Bat"
},
{
name: "john",
lastName: "smith",
fullName: "john smith",
animal: "dog",
animalSize: "middle",
animalName: "Jerry"
},
{
name: "Anna",
lastName: "Nilsson",
fullName: "Anna Nilsson",
animal: "cow",
animalSize: "big",
animalName: "Dorrie"
}
];
const filtered = usersAnimal.map((userAnimal)=>userAnimal.fullName === user.fullName && return userAnimal.animalName & userAnimal.animalSize & userAnimal.animal);
thanks
https://codesandbox.io/s/admiring-edison-qxff42?file=/src/App.js
For case like this, it would be far easier if you filter it out first then proceed using map:
const filtered = usersAnimal
.filter((animal) => animal.fullName === user.fullName)
.map(({ animalName, animalSize, animal }) => {
return {
animalName,
animalSize,
animal
};
});
I am providing a for loop solution as I haven't learnt many array methods in javascript.
For me the simplest option is to use a for loop and an if check to loop through the arrays values to check for included values.
for (let v in usersAnimal) {
if (usersAnimal[v].fullName === user.fullName) {
console.log(usersAnimal[v])
}
}
The code above will log the entire usersAnimal object containing the fullname we are looking for.
{
name: 'jan',
lastName: 'kowalski',
fullName: 'jan kowalski',
animal: 'cat',
animalSize: 'small',
animalName: 'Bat'
}
commented for further understanding
for (let v in usersAnimal) {
//loops though the array
if (usersAnimal[v].fullName === user.fullName) {
//when the index value 'v' has a fullname that matches the user fullname value
// it passes the if check and logs that object value
return console.log(usersAnimal[v])
//return true...
}
//return null
}
//etc
If you want to filter, I recommend you to use filter.
The map method will create a new array, the content of which is the set of results returned by each element of the original array after the callback function is operated
const user = {name:"jan",lastName:"kowalski",fullName:"jan kowalski",car:"audi"};
const usersAnimal = [{name:"jan",lastName:"kowalski",fullName:"jan kowalski",animal:"cat",animalSize:"small",animalName:"Bat"},{name:"john",lastName:"smith",fullName:"john smith",animal:"dog",animalSize:"middle",animalName:"Jerry"}];
// Get an array of matching objects
let filtered =
usersAnimal.filter(o => o.fullName === user.fullName);
// You get the filtered array, then you can get the required properties
filtered.forEach(o => {
console.log(
'animal:%s, animalSize:%s, animalName:%s',
o?.animal, o?.animalSize, o?.animalName
);
});
// Then use map to process each element
filtered = filtered.map(o => {
const {animal, animalSize, animalName} = o;
return {animal, animalSize, animalName};
});
console.log('filtered', filtered);
I'm not sure if I phrased the question right. I'm fairly new to JavaScript, and I'd like to add multiple objects (?) to an array.
If I have this array:
let arr = [{
firstname: "John",
lastname: "Smith"
}];
How would I add, say
var firstname = "John";
var lastname = "Doe";
as
{ firstname: "John", lastname: "Doe" }
to the same array?
Items can be added to an array with the push method. Every array has this method build it, together with many other methods, and can be used to push a new value to the end of the array.
var arr = [
{
firstname: "John",
lastname: "Smith"
}
];
In the push method create an object with the keys and the values that you want to add.
var firstname = "John";
var lastname = "Doe";
arr.push({
firsName: firstName,
lastName: lastName
});
If the keys of the object are the same name as the variables then you can use the syntax below. This will give the object keys with the same name as the variable and set the value of the variable with it as the value of the key.
arr.push({ firstName, lastName });
Alternatively if you want to add an object to the beginning of the array, use the unshift method of the array.
arr.unshift({ firstName, lastName });
You can also do this with spread operator:
var arr = [{firstname: "John", lastname: "Smith"}];
arr= [...arr, {firstname: "Name1", lastname: "LName"}]
console.log(arr);
Take a look at push.
let arr = [{
firstname: "John",
lastname: "Smith"
}];
var firstname = "soham";
var lastname = "s";
arr.push({
firstname: firstname,
lastname: lastname
})
console.log(arr);
Say I create a Object as follows
const myObj1 = {
firstName: "Shaheb",
lastName: "Ali",
professions:"Web Developer"
}
And create another object with the above object to add as a prototype object
const myObj2 = Object.create(myObj1, {
age:{
value:33
},
edu:{
value: "MBA"
}
});
now I want to count length of both object together, how can i?
I understand you want to get count of all keys in your object(s). As there is no length property available for objects (only for arrays), you should use Object.keys(), which returns an array with all keys:
const myObj1 = {
firstName: "Shaheb",
lastName: "Ali",
professions:"Web Developer"
}
Object.keys(myObj1).length; // would return '3'
I believe that instead of Object.create(), you actually want to use Object.assign(), which will assign all keys from myObj1 to myObj2:
const myObj1 = {
firstName: "Shaheb",
lastName: "Ali",
professions:"Web Developer"
}
const myObj2 = {
age:{
value:33
},
edu:{
value: "MBA"
}
}
Object.assign(myObj2, myObj1);
document.write(Object.keys(myObj2).length + '<br>'); // return '5'
document.write(Object.keys(myObj1).length); // return '3'
If I understand the OP goal:
const myObj1 = {
firstName: "Shaheb",
lastName: "Ali",
professions:"Web Developer"
}
const myObj2 = {
age:{
value:33
},
edu:{
value: "MBA"
}
};
const result = {...myObj1, ...myObj2};
console.log(result);
const length = Object.keys(result).length;
console.log(length);
{ firstName: 'Shaheb',
lastName: 'Ali',
professions: 'Web Developer',
age: { value: 33 },
edu: { value: 'MBA' }
}
5
const obj = Object.create(myObj1, myObj2);
create prototyping object looks like below
{age: 33, edu: "MBA"}
age: 33
edu: "MBA"
proto:
firstName: "Shaheb"
lastName: "Ali"
professions: "Web Developer"
proto: Object
but assigning a object is like a combining 2object into one. is this not possible to get the length from plan object and prototyping object together?
but your ans was awesome, help me a lot to make it better understand. if it is not possible then i will follow your suggestions.
Currently using the latest version of Postman: 6.7.4 (Latest)
I'm trying to get a value out of a JSON response body and store it in an environment variable BUT the value 'username' should be equal to my preferred username.
Normally I would extract a value like this:
var jsonData = pm.response.json();
pm.environment.set("useridToken", jsonData.Customers[0].userid);
This would give me the first item in the list but I do not wish to obtain the first nor the second item from the list. I wish to obtain the userid where username EQUAL "Billy" for example.
Output of the body response:
{
"Customers": [
{
"id": 24,
"userid": 73063,
"username": "BOB",
"firstname": "BOB",
"lastname": "LASTNAME
},
{
"id": 25,
"userid": 73139,
"username": "Billy",
"firstname": "Billy",
"lastname": "lasty"
}
]
}
Any tips?
I remember in SoapUI it was like this:
$.channels[?(#.is_archived=='false')].id[0]
I guess it's not possible to do this in JS in Postman?
You can use: Array.prototype.find():
const data = {
"Customers": [{
"id": 24,
"userid": 73063,
"username": "BOB",
"firstname": "BOB",
"lastname": "LASTNAME"
},
{
"id": 25,
"userid": 73139,
"username": "Billy",
"firstname": "Billy",
"lastname": "lasty"
}
]
}
const user = data.Customers.find(u => u.username === 'Billy')
const userid = user ? user.userid : 'not found'
console.log(user)
console.log(userid)
find() as another answer points out is the best solution here, but if the username is not unique and you want an array of users where username is 'Billy' then use filter()
const jsonData = {
"Customers": [{
"id": 24,
"userid": 73063,
"username": "BOB",
"firstname": "BOB",
"lastname": "LASTNAME"
},
{
"id": 25,
"userid": 73139,
"username": "Billy",
"firstname": "Billy",
"lastname": "lasty"
}
]
}
console.log(jsonData.Customers.filter(c => c.username === 'Billy'))
In Postnam test script, you can use some Javascript features. In your case, too many way to do.
I will show you how to solve your case with Array.find function:
var jsonData = pm.response.json();
var user = jsonData.Customers.find(function(user) {
return user.username === 'Billy';
// OR you could config username in postman env
// return user.username === pm.variables.get("username_to_find");
});
pm.environment.set("useridToken", user.userid);
Your userid can also be obtained using filter as follows -
const data = {
"Customers": [{
"id": 24,
"userid": 73063,
"username": "BOB",
"firstname": "BOB",
"lastname": "LASTNAME"
},
{
"id": 25,
"userid": 73139,
"username": "Billy",
"firstname": "Billy",
"lastname": "lasty"
}
]
};
const username = 'Billy';
const user = data.Customers.filter(obj => obj.username.toLowerCase() === username.toLowerCase())[0];
const userid = user ? user['userid'] : null;
console.log(userid);
Note: .toLowerCase() is optional here, you may use it depending on your condition.
Then you could simply set it as -
pm.environment.set("useridToken", userid);
This answer is inspired by the
other answer that outputs an array.
1
It is not clearly stated by the original poster whether the desired output
should be a single userid (presumably the first occurence?) - or
an array containing all userid:s matching "Billy".
This answer shows a solution to the latter case by using
Lodash.
const jsonData = {
Customers: [{
userid: 73063,
username: 'BOB'
}, {
userid: 73138,
username: 'Billy'
}, {
userid: 74139,
username: 'Billy'
}]
};
const userIds = [];
_.forEach(_.filter(jsonData.Customers, c => c.username === 'Billy'),
item => { userIds.push(item.userid); });
console.log(userIds);
<script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.17.19/lodash.js"></script>
1 That answer is quite helpful as it hints how to filter out
the relevant objects of the Customers array. However, the original poster
wants (an array of) the userid(s) which is a number, and not an an array
of objects that contains the userid:s. This is how my answer here is
different.
Try this
const userid = data.Customers.find(u => u.username === 'Billy') || 'not found';
This answer shows a solution using the JavaScript library
Lodash.
This is not meant as a recommendation, but merely to prove that it is
possible to use Lodash.
It is inspired by
the other lodash answer.1
const jsonData = {
Customers: [{
id: 24,
userid: 73063,
username: 'BOB',
firstname: 'BOB',
lastname: 'LASTNAME'
}, {
id: 25,
userid: 73139,
username: 'Billy',
firstname: 'Billy',
lastname: 'lasty'
}]
};
const userId_Lodash = (name) => {
let userId;
_.forEach(jsonData.Customers, (item) => {
if (item.username === name) { userId = item.userid; }
});
return userId;
};
console.log('Lodash loop, userid of "Billy": ' + userId_Lodash('Billy'));
console.log('Lodash loop, userid of "Dave": ' + userId_Lodash('Dave'));
<script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.17.19/lodash.js"></script>
For the question at hand, I don't see any particular reason to use the Lodash
library.
But in other examples it could make all the more sense.
1 The posted question does not state whether the desired outcome is
the first userid matching Billy, or all such userid:s.
This answer gives the first hit.
Repeating
the currently highest voted answer,
slightly modified.
Also adding a solution inspired by
the other Lodash answer.1
const jsonData = {
Customers: [{
id: 24,
userid: 73063,
username: 'BOB',
firstname: 'BOB',
lastname: 'LASTNAME'
}, {
id: 25,
userid: 73139,
username: 'Billy',
firstname: 'Billy',
lastname: 'lasty'
}]};
for (const i in jsonData.Customers) {
console.log('userid of customer['+i+']: '+jsonData.Customers[i].userid);
}
const userId_UsingFind = (name) => {
const user = jsonData.Customers.find(item => item.username === name);
return user ? user.userid : user;
};
console.log('Using .find(), userid of "Billy": '+userId_UsingFind('Billy'));
console.log('Using .find(), userid of "Joe": '+userId_UsingFind('Joe'));
const userId_Native = (name) => {
for (const i in jsonData.Customers) {
if (jsonData.Customers[i].username === name) {
return jsonData.Customers[i].userid;
}
}
};
console.log('Native loop, userid of "Billy": '+userId_Native('Billy'));
console.log('Native loop, userid of "Joe": '+userId_Native('Joe'));
As the code shows, the solution using .find() is both short and elegant.
1 Assuming the desired outcome is the userid of the first
Billy. To retrieve an array of userid:s for all occurrences
ofBilly, see the answer that returns an array of userid:s
.
I've this json return
data = [
{ firstName: "Christophe",
lastName: "Coenraets"},
{ firstName: "John",
lastName: "Smith"}
];
I want to display each object in a li list and want to use Enumerable condition. I understand if it'd been like
data = { elem :[
{ firstName: "Christophe",
lastName: "Coenraets"},
{ firstName: "John",
lastName: "Smith"}
]};
I can use something like
{{#elem}}
<li>{{firstName}} {{lastName}}</li>
{{/elem}}
But in the first case, how do I check the condition?
I don't work with icanhaz, it very well may have a method to parse the data that you get, but you could always modify the JSON object and wrap it into a parent element like in your second case:
myData = { elem : data};