javascript find index of object in 2 array - javascript

I have 2 arrays
First array has firstname and lastname
Second array only has firstname
I will index one firstname and check the arrays
function whereIsAlice(persons) {
var index = 1;
for (var i = 0; i < friends1.length; i++) {
if (friends1[i].firstName === "Alice") {
index = i;
break;
}
if (friends2[i].firstName === "Alice") {
index = i;
}
}
return index
}
var friends1 = [{
firstName: 'John',
lastName: 'Gaudet'
},
{
firstName: 'Lisa',
lastName: 'Mcclanahan'
},
{
firstName: 'Alice',
lastName: 'Vore'
}, // Alice is here, at index 2
{
firstName: 'Marine',
lastName: 'Salsbury'
},
];
var friends2 = [{
firstName: 'Tim'
},
{
firstName: 'Arthur'
},
{
firstName: 'Juan'
},
];
console.log(whereIsAlice(friends1)); //Should be 2
console.log(whereIsAlice(friends2)); // Should be -1
The output are 2 on both. How can i fix it ?

The problem its easy. You are comparing in whereIsAlice method always the first array and the second array, then the method always find the value and break de for loop.
function whereIsAlice(names) {
for (var i = 0; i < names.length; i++) {
if (names[i].firstName == "Alice") {
return i;
}
}
// When not found in above loop then return -1, not found!
return -1;
}
var friends1 = [
{ firstName: 'John', lastName: 'Gaudet' },
{ firstName: 'Lisa', lastName: 'Mcclanahan' },
{ firstName: 'Alice', lastName: 'Vore' }, // Alice is here, at index 2
{ firstName: 'Marine', lastName: 'Salsbury' }
];
var friends2 = [
{ firstName: 'Tim' },
{ firstName: 'Arthur' },
{ firstName: 'Juan' }
];
console.log(whereIsAlice(friends1)); //Should be 2
console.log(whereIsAlice(friends2)); // Should be -1

Some of You mutating new array (array.map) from initial array and doing indexOf.
Others are looping with for and then checking the variable index.
Then why JS community is working to extend language constructions, methods and etc?
I recommend You to dive in MDN better and read about findIndex ?
function whereIsAlice(persons) {
return persons.findIndex(function(person) {
return person.firstName === 'Alice';
});
}
var friends1 = [
{
firstName: 'John',
lastName: 'Gaudet'
},
{
firstName: 'Lisa',
lastName: 'Mcclanahan'
},
{
firstName: 'Alice',
lastName: 'Vore'
}, // Alice is here, at index 2
{
firstName: 'Marine',
lastName: 'Salsbury'
},
];
var friends2 = [
{
firstName: 'Tim'
},
{
firstName: 'Arthur'
},
{
firstName: 'Juan'
},
];
console.log(whereIsAlice(friends1));
console.log(whereIsAlice(friends2));
With ES6 it's so shorter that I don't see reason to create method:
console.log(friends1.findIndex(friend => friend.firstName === 'Alice'));
console.log(friends2.findIndex(friend => friend.firstName === 'Alice'));

You can do it like this if you want to write your own loop.
var friends1 = [
{ firstName: 'John', lastName: 'Gaudet' },
{ firstName: 'Lisa', lastName: 'Mcclanahan' },
{ firstName: 'Alice', lastName: 'Vore' },
{ firstName: 'Marine', lastName: 'Salsbury' },
];
var friends2 = [
{ firstName: 'Tim' },
{ firstName: 'Arthur' },
{ firstName: 'Juan' },
];
const whereIsAlice = arr => {
for (let i = 0; i < arr.length; i++) {
if (arr[i].firstName === 'Alice') {
return i;
}
}
return -1;
}
console.log(whereIsAlice(friends1)); //Should be 2
console.log(whereIsAlice(friends2)); // Should be -1

to simplify your Function you can use the next code
function whereIsAlice(persons) {
return persons.map(function(e) { return e.firstName; }).indexOf('Alice');
}
var friends1 = [{
firstName: 'John',
lastName: 'Gaudet'
},
{
firstName: 'Lisa',
lastName: 'Mcclanahan'
},
{
firstName: 'Alice',
lastName: 'Vore'
}, // Alice is here, at index 2
{
firstName: 'Marine',
lastName: 'Salsbury'
},
];
var friends2 = [{
firstName: 'Tim'
},
{
firstName: 'Arthur'
},
{
firstName: 'Juan'
},
];
console.log(whereIsAlice(friends1)); //Should be 2
console.log(whereIsAlice(friends2)); // Should be -1

Rewrite Your function as below, This will work properly in your case :
function whereIsAlice(persons) {
var index= -1;
for(var i=0;i<persons.length;i++)
if(persons[i].firstName==="Alice"){index=i;break;}
return index;
}

Related

How to fetch multiple key-value pairs array in Java Script/TestCafe

const passnegerGroup = [
{ FIRSTNAME: 'RAHUL', LASTNAME: 'KUMAR' },
{ FIRSTNAME: 'RINA', LASTNAME: 'KUMAR' },
{ FIRSTNAME: 'SOHAN', LASTNAME: 'SINGH' },
{ FIRSTNAME: 'PAUL', LASTNAME: 'ANDERSON' },
];
// I want to read each passenger's last name and first name and do some operations.
// Tried this code but this is
for (const key of Object.values(passnegerGroup)) {
console.log(key.FIRSTNAME, key.LASTNAME);
}
output :
RAHUL KUMAR
RINA KUMAR
SOHAN SINGH
PAUL ANDERSON
This is working for but getting ESLINT error.
ESLint: iterators/generators require regenerator-runtime, which is too heavyweight for this guide to allow them. Separately, loops should be avoided in favor of array iterations. (no-restricted-syntax)
Kindly help me achieve the above using some modern JavaScript/TestCafe codes.
const passnegerGroup = [
{ FIRSTNAME: 'RAHUL', LASTNAME: 'KUMAR' },
{ FIRSTNAME: 'RINA', LASTNAME: 'KUMAR' },
{ FIRSTNAME: 'SOHAN', LASTNAME: 'SINGH' },
{ FIRSTNAME: 'PAUL', LASTNAME: 'ANDERSON' },
];
//No garantee that firstname comes before lastname
const result1 = passnegerGroup.map( u => Object.values(u) ).flat().join(' ');
console.log(result1);
const result2 = passnegerGroup.map( u => [u.FIRSTNAME, u.LASTNAME]).flat().join(' ');
console.log(result2);
const passnegerGroup = [
{ FIRSTNAME: 'RAHUL', LASTNAME: 'KUMAR' },
{ FIRSTNAME: 'RINA', LASTNAME: 'KUMAR' },
{ FIRSTNAME: 'SOHAN', LASTNAME: 'SINGH' },
{ FIRSTNAME: 'PAUL', LASTNAME: 'ANDERSON' },
];
const result = passnegerGroup.reduce((accum, cur) => `${accum} ${cur.FIRSTNAME} ${cur.LASTNAME} `, '');
console.log('result =', result);

Trying to write a function to determine if a complex object's deeply nested sub array has values

I'm trying to write a function to check a deeply nested sub array inside of a complex object to return true if it has values or false if it is empty but I'm not sure how to do this.
The section I'm trying to check is contacts inside each contactGroups section which is where I'm running into issues because the array is nested 4 levels down like object > array of objects > object > contacts array and I'm not sure how to map or iterate at that level.
This is my first pass at a function which is more pseudo code at this point:
const hasContacts = (contacts: {}) => {
if(contacts.contactGroups.length === 0
|| contacts.contactGroups.map((contact) => contactGroups.contacts === undefined
|| contacts.contactGroups.map((contact) => contactGroups.contacts.length === 0 ){
return false
}
return contacts
}
The data structure looks like this:
const mockContacts = {
count: 1,
contactGroups: [
{
contactGroup: "Family",
count: 2,
contacts: [
{
member: "Uncle",
fullName: "BENJAMIN BILLIARDS",
lastName: "BILLIARDS",
firstName: "BENJAMIN",
email: "shark#billiards.com",
},
{
member: "Aunt",
fullName: "DENISE NICE",
lastName: "NICE",
firstName: "DENISE",
email: "floral#flowers.com",
}
]
},
{
contactGroup: "Friends",
count: 2,
contacts: [
{
member: "School Friend",
fullName: "DERRICK SMITH",
lastName: "SMITH",
firstName: "DERRICK",
email: "smith978#gmail.com",
},
{
member: "Work Friend",
fullName: "TARA SKY",
lastName: "SKY",
firstName: "TARA",
email: "uptown94#gmail.com",
}
]
}
If you want to return boolean if there are any contacts then you can do the following:
const hasContacts = ({ contactGroups = [] } = []) =>
contactGroups.some(
({ contacts = [] } = {}) => contacts.length
);
console.log('pass undefined', hasContacts());
console.log('pass empty object', hasContacts({}));
console.log(
'pass empty contact group',
hasContacts({ contactGroups: [] })
);
console.log(
'pass empty contacts',
hasContacts({ contactGroups: [{ contacts: [] }] })
);
console.log(
'pass contacts',
hasContacts({ contactGroups: [{ contacts: [1] }] })
);
console.log(
'pass some contacts',
hasContacts({
contactGroups: [{ contacts: [] }, { contacts: [1] }],
})
);
const mockContacts = {
count: 1,
contactGroups: [
{
contactGroup: 'Family',
count: 2,
contacts: [
{
member: 'Uncle',
fullName: 'BENJAMIN BILLIARDS',
lastName: 'BILLIARDS',
firstName: 'BENJAMIN',
email: 'shark#billiards.com',
},
{
member: 'Aunt',
fullName: 'DENISE NICE',
lastName: 'NICE',
firstName: 'DENISE',
email: 'floral#flowers.com',
},
],
},
{
contactGroup: 'Friends',
count: 2,
contacts: [
{
member: 'School Friend',
fullName: 'DERRICK SMITH',
lastName: 'SMITH',
firstName: 'DERRICK',
email: 'smith978#gmail.com',
},
{
member: 'Work Friend',
fullName: 'TARA SKY',
lastName: 'SKY',
firstName: 'TARA',
email: 'uptown94#gmail.com',
},
],
},
],
};
console.log(
'mock contacts:',
hasContacts(mockContacts)
);
Assuming the nested contactGroup contacts cannot also have more nesting then this solution should work for you. I was unclear on how you wanted to handle each nested group so I returned an array that will tell you if each nested group does or does not have contacts.
const mockContacts = {
count: 1,
contactGroups: [
{
contactGroup: "Family",
count: 2,
contacts: [
{
member: "Uncle",
fullName: "BENJAMIN BILLIARDS",
lastName: "BILLIARDS",
firstName: "BENJAMIN",
email: "shark#billiards.com",
},
{
member: "Aunt",
fullName: "DENISE NICE",
lastName: "NICE",
firstName: "DENISE",
email: "floral#flowers.com",
}
]
},
{
contactGroup: "Friends",
count: 2,
contacts: [
{
member: "School Friend",
fullName: "DERRICK SMITH",
lastName: "SMITH",
firstName: "DERRICK",
email: "smith978#gmail.com",
},
{
member: "Work Friend",
fullName: "TARA SKY",
lastName: "SKY",
firstName: "TARA",
email: "uptown94#gmail.com",
}
]
}
]
}
const hasContacts = (contacts) => {
// if contacts is not undefined, then check contactGroup
if (contacts && Array.isArray(contacts.contactGroups)) {
// we can have more than one contact group so need to check each
return contacts.contactGroups.map(row=>Array.isArray(row.contacts) && row.contacts.length > 0)
}
}
console.log(hasContacts(mockContacts))

How to check if objects in an array of objects all have specific structure and are not a null?

I receive an array of objects from the server. But my app breaks because some objects do not have a structure just a null value and my logic depends on checking against certain object keys to do one thing or another. Here is an example of an array that i receive:
[{
clienTnames: {
firstName: 'Jack',
lastName: 'Jackson'
}
}, {
clienTnames: {
firstName: 'John',
lastName: 'Johnson'
}
}, {
clienTnames: null
}]
I would like to check if any objects arrive as null and if they do switch them to empty object with all the proper keys just with no value. So if I receive clienTnames: null; I would like to automatically change it to clienTnames : {firstName: ' ', lastName: ' '}
Just use a map function:
names = names.map(name => {
return name.clienTnames
? name.clienTnames
: { clienTnames: { firstName: '', lastName: '' } }
});
You can create a defaultObj with all the default properties. Then loop through the array and update items which have clienTnames property set to null
let array = [{clienTnames:{firstName:'Jack',lastName:'Jackson'}},{clienTnames:{firstName:'John',lastName:'Johnson'}},{clienTnames:null}]
const defaultObj = {
firstName: '',
lastName: ''
}
array.forEach(a => {
if(!a.clienTnames)
a.clienTnames = { ...defaultObj }
})
console.log(array)
You can do something like this:
const data = [{ clienTnames: { firstName: 'Jack', lastName: 'Jackson' } }, { clienTnames: { firstName: 'John', lastName: 'Johnson' } }, { clienTnames: null }];
let output = [];
output = data.map(element => {
if (element.clienTnames) {
return element;
} else {
return { clienTnames: { firstName: '', lastName: '' } };
}
});
console.log(output);
let array = [{
clienTnames: {
firstName: 'Jack',
lastName: 'Jackson'
}
}, {
clienTnames: {
firstName: 'John',
lastName: 'Johnson'
}
}, {
clienTnames: null
}];
let targetArray;
targetArray = array.map((item) => {
if(!item.clienTnames) {
return { clienTnames: { firstName: '', lastName: '' } }
}
return item;
})

Reduce an array of objects and return all the original properties of the object

I have an array of objects with 4 properties each object, like this:
let arr = [
{name: john, lastName: smith, counter:1, city: New York}
{name: john, lastName: smith, counter:1, city: New York}
{name: emilio, lastName: kouri, counter:1, city: euy}
{name: john, lastName: smith, counter:1, city: New York}
]
I want to reduce it for it to return this (sum the counter)
[{name: emilio, lastName: kouri, counter:1, city: euy}
{name: john, lastName: smith, counter:3, city: New York}]
This is the code im using right now, and it reduces it correctly but only returns [counter, name], I want it to return all four properties of each object, how can it be done?
let counts = arr.reduce((prev, curr) => {
let count = prev.get(curr.name) || 0;
prev.set(curr.name, curr.counter + count);
return prev;
}, new Map());
let reducedObjArr = [...counts].map(([key, value]) => {
return {key, value}
})
console.log('reducido',reducedObjArr);
You only need one reduce statement with no nested map statements:
let arr = [{
name: "john",
lastName: "smith",
counter: 1,
city: "New York"
}, {
name: "john",
lastName: "smith",
counter: 1,
city: "New York"
}, {
name: "emilio",
lastName: "kouri",
counter: 1,
city: "euy"
}, {
name: "john",
lastName: "smith",
counter: 1,
city: "New York"
}];
let counts = arr.reduce((acc, curr) => {
if (!acc.some(({ name }) => name == curr.name)) {
acc.push(curr);
} else {
acc.find(({ name }) => name == curr.name).counter++;
}
return acc;
}, []);
console.log(counts);
You could take a copy of the object with a count of zero and increment this object and set this object.
let arr = [{ name: 'john', lastName: 'smith', counter: 1, city: 'New York' }, { name: 'john', lastName: 'smith', counter: 1, city: 'New York' }, { name: 'emilio', lastName: 'kouri', counter: 1, city: 'euy' }, { name: 'john', lastName: 'smith', counter: 1, city: 'New York' }];
let counts = arr.reduce((prev, curr) => {
let item = prev.get(curr.name) || Object.assign({}, curr, { counter: 0 });
item.counter += curr.counter;
return prev.set(curr.name, item);
}, new Map);
let reducedObjArr = [...counts.values()]
console.log('reducido', reducedObjArr);

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