I have array of objects like this:
var array = [
{
name: "John",
surname: "Doe",
title: "mister"
},
{
name: "Jane",
surname: "Smith",
title: "miss"
},
{
name: "Doe",
surname: "Mustermann",
title: "mister"
}
]
I want to implement a search term through this that will look through multiple properties while sorting them with property priority.
Example: If search term would be Doe, I would like to get this output:
[
{
name: "Doe",
surname: "Mustermann",
title: "mister"
},
{
name: "John",
surname: "Doe",
title: "mister"
}
]
name property has higher priority than surname, that's why hit on name object would go on top.
Filter function only filters through array, but I also would need to move objects up based if search term hit specific field that has higher priority.
I tried implementing this with combination of filter and sort, but unfortunately this was a failure due to both searching through multiple fields in objects, with moving some objects on top depending on which property search was found.
Have a list of fields, ordered by priority:
let fields = ['name', 'surname', 'title']
and then compute the result like this:
let result = fields.flatMap(f => array.filter(x => x[f] === search))
Related
This question already has answers here:
Merge 2 arrays of objects
(46 answers)
Closed 1 year ago.
Say I have two data arrays for a ticketed event. One is attendees:
[
{name: 'Jack', ticket_code: 'iGh4rT'},
{name: 'Lisa', ticket_code: 'it1ErB'}
]
The other is tickets:
[
{code: 'iGh4rT', name: 'General Admission'},
{code: 'it1ErB', name: 'VIP'}
]
Now say I want to display a table like this:
Name
Ticket Name
Jack
General Admission
Lisa
VIP
I am struggling with doing this efficiently. I can display a table with one array no problem like something like this:
for (let i = 0; i < attendees.length; i++){
const row = `<tr>
<td>${attendees[i].name}</td>
<td>${attendees[i].ticket_code}</td>
</tr>`
document.getElementById('TableBody').innerHTML += row
I need to somehow 'query' the tickets array with the code from the attendees array for that particular person, get the name of the ticket, and supplant the ticket name instead of the code.
With SQL something like this is easy, but is one able to "query" an array and get a specific property? Should I construct a whole new array with the needed info? What is the best way to do this that would work for large unordered datasets?
You could take one of your array as an object with code as key for the object and map the other array with wanted data and the previous stored data from the object.
const
attendees = [{ name: 'Jack', ticket_code: 'iGh4rT' }, { name: 'Lisa', ticket_code: 'it1ErB' }],
tickets = [{ code: 'iGh4rT', name: 'General Admission' }, { code: 'it1ErB', name: 'VIP' }],
ticketsByCode = Object.fromEntries(tickets.map(o => [o.code, o])),
table = attendees.map(({ name, ticket_code }) => [name, ticketsByCode [ticket_code].name]);
console.log(table);
try this:
let a = [
{name: 'Jack', ticket_code: 'iGh4rT'},
{name: 'Lisa', ticket_code: 'it1ErB'}
];
let b = [
{code: 'iGh4rT', name: 'General Admission'},
{code: 'it1ErB', name: 'VIP'}
];
let c = b.map(item => {
return {
tiketName: item.name,
...a.find(itemA => itemA.ticket_code == item.code)
}
});
console.log(c);
How to assert that all objects inside array do not include multiple properties.
Example all of them should not include keys "email" and "phone".
const myArray = [
{name: "John Doe", email: "john#gmail.com", phone: "9xxxxxxxxxx"},
{name: "Jane Doe", email: "jane#gmail.com", phone: "9xxxxxxxxxx"},
{name: "Johny Doe"}
]
// this seems to do what I want
// but doesn't "something" check if any object passes the test?
expect(myArray).to.contain.something.that.does.not.include.any.keys("email", "phone")
Using chai-things.
You can filter your array for elements having both keys set:
myArray.filter(a => a.email && a.phone)
and expect the count is 0:
expect(myArray.filter(a => a.email && a.phone)).to.be.an('array').that.is.empty;
I am creating a custom search and I have an array of objects.
const data = [{
name: "Janet McKenly",
age: 49,
city: "Baltimore",
active: "2019-02-15",
role: "Admin. Assistant"
},
{
name: "Eric Brown",
age: 23,
city: "Dallas",
active: "2020-06-01",
role: "Janitor"
},
{
name: "Nora Payne",
age: 41,
city: "Los Angeles",
active: "2020-10-02",
role: "Sales Associate"
}
]
I have another array that is dynamically created that allows only for the specific parameters to search in.
let searchColumnOnlyArray = ["name", "city", "active"]; // (generated dynamically)
role & age should not be searchable.
The goal is to only search values for keys set in searchColumnOnlyArray.
I am able to filter by hardcoding a name parameter ["name"] but the searchColumnOnlyArray is dynamic and will change... below is the method I am using:
searchTable(term: any, data: any) {
let search = data.filter((indivitem: object) => {
if(indivitem["name"] === term) {
return indivitem;
}
}
console.log("searchResults", search);
}
I need advice on how to use my searchColumnOnlyArray to only search values in those keys. Advice on how I can constrain my filter to look/search values using the set keys in searchColumnOnlyArray?
You can use the .some() method for each individual item within your filter callback. With the .some() method, you can iterate through your columns array and return true when one of the given column values (ie: keys) holds a value which matches your search term. If your .some() callback never returns true, and false for every column item/key, then the result of calling .some() will be false, which will result in the filter method not keeping the item in the final resulting array:
const data = [ { name: "Janet McKenly", age: 49, city: "Baltimore", active: "2019-02-15", role: "Admin. Assistant" }, { name: "Eric Brown", age: 23, city: "Dallas", active: "2020-06-01", role: "Janitor" }, { name: "Nora Payne", age: 41, city: "Los Angeles", active: "2020-10-02", role: "Sales Associate" } ];
const searchColumnOnlyArray = ["name", "city", "active"];
const term = "Dallas";
const search = data.filter(item =>
searchColumnOnlyArray.some(col => item[col] === term)
);
console.log("searchResults", search);
Note: In your example, you are returning the item which you want to keep in the filter method, while this works, it's not how you should be using .filter(). Your callback should be returning true/false (or a truthy/falsy value). When you return true, the current item is kept in the resulting array returned by .filter(), if you return false then it is not kept in the resulting arrray.
data.forEach(ele => {
searchColumnOnlyArray.forEach( search => {
console.log(ele[search]);
});
});
I can't try the code right now but this should do the job
I have an array of objects (student objects which have properties like studentID, grade, dob, registeredDate) and I have another array of objects (books objects which have properties studentID, bookID, bookISBN).
It's a Web app for managing the library at a small school. What I want to do is that when a book (say has title Welcome Home) has been borrowed by student with studentID 4, when you try to lend that book (of course a copy since the library can have a number of them in stock) to someone else, the student with studentID 4 shouldn't be available in the list of students who are eligible to get that book (unless if the student had returned the book first).
The booksList Array is like below:
[
{
bookEdition: "2nd edition",
bookISBN: 9876533278765,
bookStatus: 0,
bookTitle: "Real Machines",
dateTaken: "2018-10-28",
returnDate: "2018-11-27",
studentID: "0000003"
},
{
bookEdition: "2015 edition",
bookISBN: 9876532226712,
bookStatus: 0,
bookTitle: "Real Machines",
dateTaken: "2018-08-28",
returnDate: "2018-09-27",
studentID: "0000004"
}
];
The studentsList is as below:
[
{
bio: "Needs extra work. Has problems with mathematics",
birthday: "2005-05-12",
className: "grade 5",
fullname: "Bridget Friday",
gender: "Female",
parentName: "Josam Friday",
studentID: "0000003",
studentStatus: "approved"
},
{
bio: "A bit naughty but intelligent. Pay close attention to his diet.",
birthday: "2003-11-07",
className: "grade 6",
fullname: "Charles Ben",
gender: "Male",
parentName: "Chris Ben",
studentID: "0000004",
studentStatus: "approved"
}
];
Now, I was trying to use the filter function but it doesn't give me the results I want. The thing that links the two array objects and the objects in them is the studentID.
I tried
var legitStudents = studentsList.filter(el => {
return !booksList.includes(el.studentID);
});
The above doesn't work. The arrays (studentList and booksList) are fetched dynamically and I can't tell which studentIDs are in booksList.
How can I get this to work as I want them?
return !booksList.includes(el.studentID);
should be
return !booksList.map(i => i.studentID).includes(el.studentID);
As a couple people said in the comments of your question, the problem is your code is expecting booksList to be an array of studentIDs. Since it's actually a list of books that have been checked out by students, you first need to make an array of all studentIDs in booksList then you can use includes on the resulting array. See map.
You can use Rocky Sims' solution or you can try this as well
var legitStudents = studentList.filter(student => {
return !booksList.filter(book => book.studentID === student.studentID).length;
});
I'm still learning javascript patterns, and I'm curious about this one.
If I have an array of objects, should I make the array of objects not have keys (Example A), or use their keys (Example B)?
An array of objects without any key:
var soylent_green_candidates = [{
id: 12341,
name: "Don",
gender: "Male",
weapon_of_choice: "Kangaroo Cannon"
},
{
id: 24325,
name: "Jimmy",
gender: "Male",
weapon_of_choice: "Sushi Blaster"
},
...
]
Or an array of objects using the unique ID's as keys:
var soylent_green_candidates = [
12341: {
name: "Don",
gender: "Male",
weapon_of_choice: "Kangaroo Cannon"
},
24325: {
name: "Jimmy",
gender: "Male",
weapon_of_choice: "Sushi Blaster"
},
...
]
Your second example is invalid, so that should put the question to sleep.
In Javascript you have the option of arrays, which are sorted but essentially "key less". Each array entry can only be accessed by its numeric index, period.
The other option is objects, which have no guaranteed order but are keyed by arbitrary values.
['foo', 'bar', 'baz']
{ foo : 'bar', baz : 42 }
You make the choice based on these two criteria, order and requirement for keys.
(Note: while you can use arbitrary numeric indices for arrays, you can't do so using the literal syntax [..], and it's not usually a good idea. If you need explicit keys, you want objects.)