Loop through an array of objects and sort them - javascript

I have an array containing some objects and I am trying to loop through it where I have data stored in the following order:
firstName: Alice
lastName: Wonderland
age:12
I am trying to loop, then to sort it in descending order where age: value should be in first position then > lastName: Wonderland comes and lastly firstName.
Here is my code until this moment
var data = {
example1: [{
firstName: 'Alice',
lastName: 'Wonderland',
age: 12
}],
example2: [{
firstName: 'Thomas',
lastName: 'Mathison',
age: 14
}],
example3: [{
firstName: 'David',
lastName: 'Jacobsen',
age: 18
}]
};
for (var key in data) {
var arr = data[key];
for (var i = 0; i < arr.length; i++) {
var obj = arr[i];
for (var prop in obj) {
if (obj.hasOwnProperty(prop)) {
console.log(prop + ': ' + obj[prop]);
}
}
}
}
I want to achieve the reverse order (descending) when I output the result in the console.log();:
age: 12,
lastName: 'Wonderland',
firstName: 'Alice'
age:14,
lastName: 'Mathison',
firstName: 'Thomas'
age:18,
lastName: 'Jacobsen',
firstName: 'David'
I am not sure about the sort function behavior. How should it work during the loop?
Any suggestions?

var data = {
example1: [{
firstName: 'Alice',
lastName: 'Wonderland',
age: 12
}],
example2: [{
firstName: 'Thomas',
lastName: 'Mathison',
age: 14
}],
example3: [{
firstName: 'David',
lastName: 'Jacobsen',
age: 18
}]
};
var objectArray=[];
for (var key in data) {
var arr = data[key];
for (var i = 0; i < arr.length; i++) {
var obj = arr[i];
objectArray.push(obj);
}
}
objectArray.sort(function(element1,element2){
return element2.age - element1.age
}); //now iterate over the array it is sorted in descending order

Sorting arrays of non-primitive data types (custom objects and data structures like in your case) require two steps. It's quite straightforward so follow along.
First you need to create a function capable of comparing two objects of your custom data structure according to your desired criteria.
Second, you provide this decision function to a sort function along with your array and it will use it to sort the array for you. Lets do it for your case:
First the compare function, a and b are objects from your custom structure. returning 1 means object a is "bigger", returning -1 means b is "bigger", returning 0 means that, according to your criteria, both are equal in "size". The order of the if statements bellow is naturally important and reflects the priorities you described:
age takes priority over names and last-name over first-name.
function compare_people(a, b) {
if (a.age < b.age) {
return -1;
}
if (a.age > b.age) {
return 1;
}
if (a.lastName < b.lastName) {
return -1;
}
if (a.lastName > b.lastName) {
return 1;
}
if (a.firstName< b.firstName) {
return -1;
}
if (a.firstName> b.firstName) {
return 1;
}
return 0;
}
Now all you have to do is provide your criteria and array to javascript's sort function. In your case objects are stored inside the data array, so you do:
data.sort(compare_people);
Done, array sorted!
Here you can study the concept more in depth https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/sort
Good luck.

Apparently the question is not clear enough, people keep giving you sorting algorithms which I understand it is not what you are looking for, you want to change the internal order of the properties (which makes no sense, they have no 'order' they are part of a map, in any case, here is what I would do:
var data = {
example1: [{
firstName: 'Alice',
lastName: 'Wonderland',
age: 12
}],
example2: [{
firstName: 'Thomas',
lastName: 'Mathison',
age: 14
}],
example3: [{
firstName: 'David',
lastName: 'Jacobsen',
age: 18
}]
};
for (var key in data) {
var arr = data[key];
var newArr = [];
for (var i = 0; i < arr.length; i++) {
var obj = arr[i];
newArr.push({
age: obj.age,
firstName: obj.firstName,
lastName: obj.lastName
})
}
data[key] = newArr;
}
But again, what you are trying to do makes no sense, or at least according to the description.

Use [].unshift() method
var result = [];
for (var key in data) {
var arr = data[key];
for (var i = 0; i < arr.length; i++) {
var obj = arr[i];
for (var prop in obj) {
if (obj.hasOwnProperty(prop)) {
result.unshift(prop + ': ' + obj[prop])
}
}
}
}
console.log(result)
here is demo https://plnkr.co/edit/N4Zt28zh0A3MpwoOrzmZ?p=preview

Related

Iterate through Array of objects and if all key values equal the same return true else false Javascript

I have the below array of objects I basically want to compare the values in the language keys and if all are the same return true else return false. Any ideas would be appreciated.
var list1 = [
{ firstName: 'Daniel', lastName: 'J.', country: 'Aruba', continent: 'Americas', age: 42, language: 'JavaScript' },
{ firstName: 'Kseniya', lastName: 'T.', country: 'Belarus', continent: 'Europe', age: 22, language: 'JavaScript' },
{ firstName: 'Hanna', lastName: 'L.', country: 'Hungary', continent: 'Europe', age: 65, language: 'JavaScript' },
];
function isSameLanguage(list) {
let counter =0;
for (let i=0; i<=list.length; i++){
counter = counter = counter +1
if (list.language[i] == list.language[i]){
//console.log("Match")
}
}
}
What you're looking for the is the every method. In your case it'd look something like this:
function isSameLanguage(list) {
if (!list.length) return false; // guard to prevent the next line from throwing an error
const firstLanguage = list[0].language;
return list.every(item => item.language === firstLanguage);
}
You don't need a counter variable.
list.language[i] == list.language[i] in the context of your data doesn't make sense. It's the index of the object, not the index of the language. So: list[i].language, and you can compare that to the next element in the array: list[i].language !== list[i + 1].language. If they don't match return from the loop ("No match"), otherwise, wait for the loop to complete ("Match").
Example one where they all do match:
const list1=[{firstName:"Daniel",lastName:"J.",country:"Aruba",continent:"Americas",age:42,language:"JavaScript"},{firstName:"Kseniya",lastName:"T.",country:"Belarus",continent:"Europe",age:22,language:"JavaScript"},{firstName:"Hanna",lastName:"L.",country:"Hungary",continent:"Europe",age:65,language:"JavaScript"}];
function isSameLanguage(list) {
for (let i = 0; i < list.length - 1; i++) {
if (list[i].language !== list[i + 1].language) {
return 'No match';
}
}
return 'Match';
}
console.log(isSameLanguage(list1));
Example two where they don't:
const list1=[{firstName:"Daniel",lastName:"J.",country:"Aruba",continent:"Americas",age:42,language:"JavaScript"},{firstName:"Kseniya",lastName:"T.",country:"Belarus",continent:"Europe",age:22,language:"JavaScript"},{firstName:"Hanna",lastName:"L.",country:"Hungary",continent:"Europe",age:65,language:"JavaScript2"}];
function isSameLanguage(list) {
for (let i = 0; i < list.length - 1; i++) {
if (list[i].language !== list[i + 1].language) {
return 'No match';
}
}
return 'Match';
}
console.log(isSameLanguage(list1));

Having trouble finding value with for-in loop

I am attempting to loop through this array's objects elements and return 'gotcha, bill' when the 'for in' loop finds the value 'bill'. However, it only seems to return 'not him' four times. I've skimmed over it several times and I'm not sure what I am missing. This is my first time using a for in loop, so I could be misunderstanding how it works.
Any help would be appreciated!
var names = [{name: 'steven', age: 22}, {name: 'bill', age: 13}];
function findBill(array) {
for(let i = 0; i < array.length; i++) {
for(let key in array[i]) {
if(key === 'bill') {
return console.log('gotcha, bill');
} else {
console.log('not him');
}
}
}
}
findBill(names)
for..in iterates over an object's keys. Since bill is a value, not a key, the (key === 'bill') test will never evaluate to true.
If you wanted to iterate over the object's values instead, use Object.values, and since it sounds like you want to find the bill object, you can use .find:
var names = [{name: 'steven', age: 22}, {name: 'bill', age: 13}];
function findBill(array) {
return array.find((obj) => (
Object.values(obj).includes('bill')
))
};
console.log(findBill(names))
If you know in advance that the value will be in the name property, then just test that property, rather than using Object.values:
var names = [{name: 'steven', age: 22}, {name: 'bill', age: 13}];
function findBill(array) {
return array.find((obj) => (
obj.name === 'bill'
))
};
console.log(findBill(names))
Here. I changed your for loop to forEach but that is not the main thing that solves your problem. It is how you access the object's property. I use forEach because it will be easier (for me) to get the desired data from the object.
var names = [{name: 'steven', age: 22}, {name: 'bill', age: 13}];
function findBill(array) {
array.forEach(function(person){
if(person.name === 'bill') {
return console.log('gotcha, bill');
} else {
console.log('not him');
}
});
}
findBill(names)
And this is how it should be if you insist on using for loop.
var names = [{name: 'steven', age: 22}, {name: 'bill', age: 13}];
function findBill(array) {
for(let i = 0; i < array.length; i++) {
if(array[i].name === 'bill') {
return console.log('gotcha, bill');
} else {
console.log('not him');
}
}
}
findBill(names)
key is exactly that--the keys of each object, namely, name or age. You need to actually index into the array at the correct index, then access the value for the key you're inspecting in the loop with if (array[i][key] === 'bill').
Here's a working example:
var names = [{name: 'steven', age: 22}, {name: 'bill', age: 13}];
function findBill(array) {
for(let i = 0; i < array.length; i++) {
for(let key in array[i]) {
if(array[i][key] === 'bill') {
return console.log('gotcha, bill');
} else {
console.log('not him');
}
}
}
}
findBill(names);
However, the extra loop isn't necessary and causes logic errors because you might have some other key, say, buffalo that happens to have the value "bill" and you'll wind up with a false positive. You know the key, so you can simply search the array for any object with the matching value for that key:
var names = [{name: 'steven', age: 22}, {name: 'bill', age: 13}];
console.log(names.find(e => e.name === "bill"));
Lastly, I recommend avoiding console.log in functions, which is a side effect that limits reusability. console.log returns undefined after printing, so it's misleading to return this, even in simple or contrived examples.
You don't need two loops for this. In fact you can use the Array.find() method to find the object you need and do with it what you need:
const people = [{name: 'steven', age: 22}, {name: 'bill', age: 13}];
const findByName = (data, name) => data.find(cur => cur.name === name);
const Bill = findByName(people, 'bill');
if (Bill === null) { console.log(`could not find bill`); }
else { console.log(`bill is ${Bill.age} years old`); }

indexOf method for array of objects in Javascript

I have array of objets like:
var MyArray = [] ,
Person = {},
[
{
name: 'John',
surname: 'Smith',
age: '22'
},
{
name: 'Jesica',
surname: 'Garou',
age: '31'
},
{
name: 'Max',
surname: 'Jolie',
age: '50'
}
]
I want to check , if my data has name 'John' that don't add new person , if not , then add new person with name 'John' and etc.
Thanks in advance .
You could deal with it using Array#find. I assume that you want to mutate your original array.
let arr = [{
name: 'Jesica',
surname: 'Garou',
age: '31'
},
{
name: 'Max',
surname: 'Jolie',
age: '50'
}
];
const obj = {
name: 'John',
surname: 'Smith',
age: '22'
};
const ensure = ({ name, ...z }) => {
if (!arr.find(v => v.name === name)) {
arr.push({ name, ...z });
}
}
ensure(obj);
console.log(arr);
You can use map but you have to know that map iterates through all elements in the array, whereas findIndex returns the first element index that equals the condition and stops the loop.
var MyArray = [
{
name: 'John',
surname: 'Smith',
age: '22'
},
{
name: 'Jesica',
surname: 'Garou',
age: '31'
},
{
name: 'Max',
surname: 'Jolie',
age: '50'
}
];
if(MyArray.findIndex(index => index.name === "John") > -1)
console.log("Found!");
else
console.log("Not found!");
To check if a name already exists in an array, you can make use of array.some function. It will check if name provided already exits or not.
If not then you can write the code to push the object in the array.
I have used the sample names John and Anne. For John, the function isAlreadyPresent returns true. For Anne, it returns false.
let arr = [
{
name: 'John',
surname: 'Smith',
age: '22'
},
{
name: 'Jesica',
surname: 'Garou',
age: '31'
},
{
name: 'Max',
surname: 'Jolie',
age: '50'
}
];
function isAlreadyPresent(name) {
return arr.some(a => a.name === name );
}
console.log('John already exists?',isAlreadyPresent('John'));
console.log('Anne already exists?',isAlreadyPresent('Anne'));
Maybe a name Map could be useful:
var byNam e =new Map(myArray.map(el=>[el.name,el]));
So you can easily do:
if (byName.has("John")){
alert("already exists");
} else {
var obj = { name: "John" };
Map.set(obj.name,obj);
myArray.push(obj);
}
The upper can be achieved with a Set also, but you may also want to do this:
byName.get("John").age=15;
You'll need to loop through all of the objects and check each of their name values. At worst runs in O(n) time.
For example, to check if "John" is a name in the array:
var inArray = false; // Have we found the name in the array yet?
for (var i = 0; i < MyArray.length; i++) { // Loop through the array of objects
if (MyArray[i].name=="John") { // If the name field is equal to "John"
inArray = true; // Name is in the array
break; // Exit the loop
}
}
var searchTerm = "John",
index = -1;
for(var i = 0, len = MyArray.length; i < len; i++) {
if (MyArray[i].name === searchTerm) {
alert("matched string");
index = i;
break;
}
}
You can make a search function like this that:
const index = (array, name) => {
// Search for the string "name" in your array
for (let i in array){
// Look at every element in the array, if an element has the
// corresponding name, return its index
if (array[i].name === name) return i;
}
return -1;
// If you found nothing, return -1
}
let position = index(myArray, "John");
Traditionally we use a constructor to build many similar objects. However, how that is OOP and is out of the scope of what you are asking.
Here we can use a for... in loop to iterate though MyArray, and check that each object does not include the name John.
function addJohn () {
for (let iterator in MyArray) { // You can also use for... of, but it will break in Node.
if (MyArray[iterator].name == "John") {return}; //You can also replace the string with a variable name to check that all objects do not have the variable in them.
else continue;
}
// you can now put in your new object here.
}

How can I return an object out of an array? [duplicate]

This question already has answers here:
Get JavaScript object from array of objects by value of property [duplicate]
(17 answers)
Closed 6 years ago.
I have an array of objects and I wanted to search through each object and check if the data matches a given value and I want to return the object out of the array and if it is not found then I have to return undefined.
This is what I have so far:
var data = [{
id: 1,
firstName: 'John',
lastName: 'Smith'
}, {
id: 2,
firstName: 'Jane',
lastName: 'Smith'
}, {
id: 3,
firstName: 'John',
lastName: 'Doe'
}];
var asf[] = data[0];
return asf;
I'm trying to return the object if the condition in if else statement matches but it gives me error in returning array object.
I am also trying to use _.findwhere(data, pid) which is method in module of underscore can I use it to return the object out of array?
You can use Array.prototype.find(), like this:
var data = [{
id: 1,
firstName: 'John',
lastName: 'Smith'
}, {
id: 2,
firstName: 'Jane',
lastName: 'Smith'
}, {
id: 3,
firstName: 'John',
lastName: 'Doe'
}];
data.find(x => {x.id === 1});
If you like to know more about arrays vist this link.
http://exploringjs.com/es6/ch_arrays.html
I'm not sure if you want to return the object or remove the object so I'll show you how to do both as both are very simple to do.
This is a tidied version of your data:
// this is your data
var data = [{
id: 1,
firstName: 'John',
lastName: 'Smith'
}, {
id: 2,
firstName: 'Jane',
lastName: 'Smith'
}, {
id: 3,
firstName: 'John',
lastName: 'Doe'
}];
This the loop you'll use to return the target object from the array:
// loop through the data array
for(var i = 0; i < data.length; i++) {
// check if the current item is "John Smith"
if(data[i].firstName == "John" && data[i].lastName == "Smith") {
return data[i];
}
// continue with the loop if the current item is not "John Smith"
continue;
}
This snippet does the exact same thing but without the continue:
// loop through the data array
for(var i = 0; i < data.length; i++) {
// check if the current item is "John Smith"
if(data[i].firstName == "John" && data[i].lastName == "Smith") {
return data[i];
}
}
This the loop you'll use to remove the target object from the array:
// loop through the data array
for(var i = 0; i < data.length; i++) {
// check if the current item is "John Smith"
if(data[i].firstName == "John" && data[i].lastName == "Smith") {
delete data[i];
// you can also use Array.prototype.splice() to remove an item from an array:
// data.splice(i, 1);
}
// continue with the loop if the current item is not "John Smith"
continue;
}
This snippet does the exact same thing but without the continue:
// loop through the data array
for(var i = 0; i < data.length; i++) {
// check if the current item is "John Smith"
if(data[i].firstName == "John" && data[i].lastName == "Smith") {
delete data[i];
// you can also use Array.prototype.splice() to remove an item from an array:
// data.splice(i, 1);
}
}
Use this snippet if you are using jQuery, instead of returning or deleting anything you can handle the object however you please inside the jQuery callback function.
In this case, I'll be using console.log(); as an example:
$.each(data, function(i, object) {
if(object.firstName == "John" && object.lastName == "Smith") {
console.log(object);
}
});
Good luck and all the best.
Vanilla JS:
var findWhere = function(key,val,array) {
var o;
array.some(function(object) { return object[key] == val && (o = object); });
return o;
};
var data = []; //your array
findWhere('id',1,data); //get the first object in the array where id = 1
EDIT
Here's a better one that actually takes a callback and can return just one element, or all matching elements:
var find = function(arr,cb,all) {
var o;
if(all) {
return arr.filter(cb);
}
arr.some(function(object) { return cb(object) && (o = object); });
return o;
};
var findAll = function(arr,cb) { return find(arr,cb,true); };
//return the first object in the data array where the id = 1
find(data,function(object) { return object.id == 1 });
//return all objects in the data array where name = 'John'
findAll(data,function(object) { return object.firstName = 'John'; });

How to skip same values and get array length

I have my example array:
var person = [{
firstName:"John",
lastName:"Doe",
age:46
},
{
firstName:"Alexander",
lastName:"Bru",
age:46
},
{
firstName:"Alex",
lastName:"Bruce",
age:26
}];
Simple person.length gives me the length of my array, but I need to merge values when the age is the same. So if two people have same age return 1 no 2. Sorry for my bad English, I can made a mistakes.
Use Array#forEach method with an object reference for age.
var person = [{
firstName: "John",
lastName: "Doe",
age: 46
}, {
firstName: "Alexander",
lastName: "Bru",
age: 46
}, {
firstName: "Alex",
lastName: "Bruce",
age: 26
}];
// object for storing reference to age
var obj = {},
res = 0;
// iterate and count
person.forEach(function(v) {
// check age already not defined
if (!obj[v.age]) {
// define the property
obj[v.age] = true;
// increment count
res++;
}
});
console.log(res);
you can use underscore or similar library that supports groupBy:
_.size(_.groupBy(person, "age"))
Filter the array down to only those elements for which a find on the array for the first element with the same age yields the element itself, then take the length of the result:
array.filter(o1 => o1 === array.find(o2 => o2.age === o1.age)).length
Another idea involves using a little function called uniqueCount, which counts the number of unique values in a (sorted) array:
function uniqueCount(a) {
return a.reduce((cnt, elt, i) => a[i] === a[i-1] ? cnt : cnt + 1), 0);
}
Now you can create an array of all the ages, and do a count of its unique elements on it:
uniqueCount(array.map(e => e.age).sort(numeric))
If you are allowed to, you could add all the ages to a set and take its size.
const people = [{
firstName: "John",
lastName: "Doe",
age: 46
}, {
firstName: "Alexander",
lastName: "Bru",
age: 46
}, {
firstName: "Alex",
lastName: "Bruce",
age: 26
}];
const ages = new Set(people.map(person => person.age));
console.log(ages.size)

Categories

Resources