Extract 1 of each property from object - javascript

I am looking for a method using lodash/underscore(or plain JS if one does not exist) that will only me to take a given object such as below.
animals: {
{
type: 'duck',
name: 'quack',
},
{
type: 'duck',
name: 'quieck',
},
{
type: 'dog',
name: 'bark',
},
},
This object for example contains 3 different animals, but two of them are the same type.
The end result is to be able to use a control structure such as a for loop to iterate through each TYPE of animal, such that I'm working with something that only has one instance of each type.
This is being used because I am creating a list.
This list will be similar to the following
duck
name is quack
name is quick
dog
name is bark
But i want to do this with control structures and not by simply outputting and hardcoding in each name, as this list will get very extensive and long.

I would use the uniq function.
var uniqueAnimals = _.uniq(animals, function(item, key, type) {
return item.type;
});

Presuming animals is not a syntax error, but an array: If you don't just want to filter the unique types but also create a structure for your output, you could go with an object:
var kv = {};
animals.forEach(function(a) {
if(kv[a.type]) {
kv[a.type].push(a.name);
} else {
kv[a.type] = [];
}
}
Later, you could iterate Object.keys(kv) to print your key/values

_.groupBy() maybe?
var animals = [
{
type: 'duck',
name: 'quack',
},
{
type: 'duck',
name: 'quieck',
},
{
type: 'dog',
name: 'bark',
},
];
var grouped = _.groupBy(animals, 'type');
document.write('<pre>' + JSON.stringify(grouped, null, 3) + '</pre>');
<script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.6.1/lodash.min.js"></script>

Related

return the value with an array of objects

I thought using bracket or dot notation with people.pets or people[pets] would return the results of the pets but not having luck.
This function will be called with an array of objects. Each object
represents an owner and will have a pets property, which will be an
array of pet names. The function should return an array of all the
pets' names.
If passed an empty array the function should return an empty array.
A typical array of owners is shown below:
[
{
name: 'Malcolm',
pets: ['Bear', 'Minu'],
},
{
name: 'Caroline',
pets: ['Basil', 'Hamish'],
},
];
That would be a perfect example for the use of the Array.reduce().
It would however keep duplicates names. Let's say if two owners had the same pet name, it would appear twice, so it depends on what you want.
const owners = [
{ name: "Malcolm", pets: ["Bear", "Minu"] },
{ name: "Caroline", pets: ["Basil", "Hamish"] },
];
const pets = owners.reduce((acc, item) => acc.concat(item.pets), []);

Javascript: How to iterate through an array looking for an object value?

I have a js file that is just a an array with the name and type of person. I am trying to write a function in my other file to iterate through that array of objects and return just the object that matches a certain criteria. Here is my code.
person.js
export const persons_options = [
{
name: 'Andrew',
type: 'Athlete',
},
{
name: 'Paul',
type: 'Worker',
},
{
name: 'Phil',
type: 'Developer',
},
]
utils.js
// params initialized already
person_type = params.subType
const name = persons_options.map((option) => {
if(person_type === option.type){
return option.name
}
})
const person = name
The issue is I know map creates a new array so the output is ,,Phil. How would I just return one of the object names instead of all of them.
find() will do the work
let persons_options = [
{
name: 'Andrew',
type: 'Athlete',
},
{
name: 'Paul',
type: 'Worker',
},
{
name: 'Phil',
type: 'Developer',
},
]
let obj = persons_options.find(o => o.type === 'Developer');
//to return name
console.log("name",obj.name);
console.log(obj);
You need to use the find function.
See here the list of functions that you can call on an array:
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array#instance_methods
filter might best suit your case if multiple results may be returned.

Loop through an array of objects and get where object.field equals value

I'm currently working on a small application where I have to loop through an enormous array of objects. What would be the most efficient method to perform this?
var array = [
{
id: "1",
name: "Alpha"
},
{
id: "2",
name: "Beta"
},
...
];
I'd like to get each object where name equals "Alpha". I'm currently using a simple if statement to filter the objects with a different name value out, but I wonder if there's a more efficient way to do this, performance-wise.
It's worth to mention that I'll push the matching results into a new array.
No, there is no more efficient way.
The alternative is to build and maintain some kind of internal data structure which allows you to find the desired elements faster. As usual, the trade off is between the work involved in maintaining such a structure vs the time it saves you.
I don't have any way about which I would know it's more effective.
But if you had your objects ordered by name you could stop your search imideatly upon reaching an object whose name is not equal to "Alpha".
To find the first object you're looking for you can use binary search and from this Object you go up and down until at both ends you reach an object which isn't named "Alpha" or the end of array.
This is only a way of optimizing and will require time to sort the array and also will take more time when adding an element.
There's a JavaScript function exactly for this kind of task. Filter
From the Docs
The filter() method creates a new array with all elements that pass the test implemented by the provided function.
Here is a small example by code for getting all element from array which has a certain 'name' field:
const arr = [
{name: 'Abc'},
{name: 'Xyz'},
{name: 'Lmn'},
{name: 'Xyz'},
{name: 'Xyz'}
];
let response = findByName('Xyz');
console.log(response);
function findByName (name) {
return arr.filter((element) => {
return element.name = name;
});
}
If you need more than one time a collection with a given name, you could use an object with the names as hashes and have instantly access to the items.
var array = [{ id: "1", name: "Alpha" }, { id: "2", name: "Beta" }, { id: "3", name: "Beta" }, { id: "4", name: "Gamma" }, { id: "5", name: "Beta" }, { id: "2", name: "Alpha" }],
hash = Object.create(null);
array.forEach(function (a) {
if (!hash[a.name]) {
hash[a.name] = [];
}
hash[a.name].push(a);
});
console.log(hash);
.as-console-wrapper { max-height: 100% !important; top: 0; }

How to create json array with the inner array in javascript and access it

I want to create an object with an array property which looks like this:
var arrayOfUsers = {
id: "some user id",
username : "some names",
roles : [array with roles]
}
And i would like to access an element by id, something like, arrayOfUsers['some id']['roles'];
I am new to json. I've tried different ways, but always ended up with bunch of errors.
First, this is a JavaScript object. JSON is a string representation of JavaScript objects.
Second, it's important to know the difference between an object and an array. In general, consider Objects to be defined with curly braces { } and Arrays with braces [ ]
Values in Arrays are accessed by their index with the arr[index] syntax while objects use obj[key] syntax to access the value assigned to some key on the object.
For your scenario, I'd avoid using arrays, because you want to be able to access objects by key, not by index.
var users = {
"some user id": {
username : "some names",
roles : {
"some role id": {
name: "role name"
}
}
}
};
In reality, this isn't a very effective data structure, because you'd likely want to deal with arrays for looping, rendering, etc, but to answer your question about being able to index by the Id of user and role, this is how your data would have to be structured.
Here is how you declare:
var currentUser,
currentRole,
arrayOfUsers = {
id: 1,
username: "Sample Value",
roles: [{
roleId: 1,
name: "Admin"
},
{
roleId: 2,
name: "Cashier"
}]
};
This is how you access it:
for (var i = arrayOfUsers.length; i--;) {
currentUser = arrayOfUsers[i];
for (var x = currentUser.roles.length; x--;) {
currentRole = currentUser.roles[x];
console.log("ID=" + currentRole.id + "Name=" + currentRole.name);
}
}
First, you have to make difference between array which defined by [], and Objects, by {}.
If you want to make an array of JSON, you can do the following :
var arrayRoles = [{
idRole: 1,
type: 'admin'
}, {
idRole: 2,
type: 'user'
}];
var userArray = [{
id: 1,
username: 'toto',
roles: arrayRoles
}, {
id: 2,
username: 'titi',
roles: arrayRoles
}, {
id: 3,
username: 'toto',
roles: arrayRoles
}];
Then, if you want to iterate over all your data, you can do it by using forEach loop, which tends to be more elegant :
userArray.forEach(function(elm){
//Our roles array
var roles = elm.roles;
//For all item in roles array
roles.forEach(function(value){
//display type of role, for example.
console.log(value.type);
});
});
But if you want to search a specific item in your JSON array, you can use filter method, by using high order function.
function filterBy(key, filter){
return function(elm){
return elm[key] === filter;
}
}
Then, you can apply this function to your filter, by passing specific field and value, and it will return an array of results :
var filtered = userArray.filter(filterBy('username', 'toto'));
//Display '1'
console.log(filtered[0].id);
//Display '3'
console.log(filtered[1].id);

Filter response object based on an array of whitelisted ids

How to Filter a response object based on an array of whitelisted ids?
I've a working version but i don't like the nested forEach here and i wonder if there is a way to improve it?!
function WhitelistCtrl($scope) {
var visible = [];
var whitelist = [123, 456]; // items to be visible
var response = [{
id: 123,
name: 'my object #1'
}, {
id: 456,
name: 'my object #2'
}, {
id: 789,
name: 'my object #3'
}];
angular.forEach(whitelist, function (id) {
angular.forEach(response, function (item) {
if (id === item.id) {
visible.push(item);
}
});
});
}
Here is a JSFiddle to play with: http://jsfiddle.net/gearsdigital/rv6vq2L7/
I'm not much familiar with Anglar ForEeach but you can achive this using native javascript filter like bellow
visible = response.filter(function(item){
return (whitelist.indexOf(item.id) > -1);
})
DEMO
NOTE:- IE8 doesn't supports .filter.

Categories