I have an array of objects where I want to find out what consecutive days are the most common between all of them and then choose the first day of that consecutive day pair.
let data = [
{
name: "mike",
city: "Los Angeles",
days: ["2020-01-02", "2020-01-03","2020-01-18", "2020-01-19"]
},
{
name: "Kenny",
city: "Chicago",
days: ["2020-04-02", "2020-04-12","2020-04-19"]
},
{
name: "James",
city: "Los Angeles",
days: ["2020-05-02", "2020-05-12","2020-05-19"]
},
{
name: "Maggie",
city: "Los Angeles",
days: ["2020-11-12", "2020-11-13","2020-05-19"]
},
{
name: "Ricardo",
city: "Los Angeles",
days: ["2020-01-02", "2020-01-03","2020-05-19"]
},
{
name: "Reeny",
city: "Chicago",
days: ["2020-01-02", "2020-01-04","2020-05-09"]
},
];
so for example, for Los Angeles, I'd want to return:
{
city: "Los Angeles",
day: "2020-01-02",
people: ["mike", "ricardo"],
}
"Maggie" wouldn't be in since her available consecutive days appear less than Mike and James.
For Mike and James, "2020-01-02" and "2020-01-03" appears most for Los Angeles.
For Chicago, I'd want to return just an empty string since I don't have any consecutive days.
So far, I iterated through the data and pushed the city to an object. If the city is already in the object, I push each day to the existing array. If the city is not in the hash object, then I just set it and have it equal the days
let obj = {};
data.forEach(x => {
if (map[x.city]) {
x.days.forEach(y => {
map[x.city].push(y);
})
} else {
map[x.city] = x.days;
}
});
for (x in obj) {
let arr = [...new Set(obj[x])]
obj[x] = arr.sort();
}
my result is an object with the city as a key and the value is the days (with the duplicates removed via Set) :
obj = {
"Los Angeles": ["2020-01-02", "2020-01-03","2020-01-18", "2020-01-19", "2020-05-02", "2020-05-12","2020-05-19", "2020-11-12", "2020-11-13"],
"Chicago": ["2020-01-02", "2020-01-04","2020-04-02", "2020-04-12","2020-04-19", "2020-05-09"]
}
From this point, I'm not sure what to do. I imagine it's possible to accomplish this but I don't know the next step here.
You can use alasql
https://github.com/agershun/alasql/wiki/Examples
with alasql can you make: DISTINCT or GROUP etc.
example:
// Fill table with data
var person = [
{ name: 'bill' , sex:'M', income:50000 },
{ name: 'sara' , sex:'F', income:100000 },
{ name: 'larry' , sex:'M', income:90000 },
{ name: 'olga' , sex:'F', income:85000 },
];
// Do the query
var res = alasql("SELECT * FROM ? person WHERE sex='F' AND income > 60000", [person]);
document.getElementById("result").innerHTML = JSON.stringify(res);
Related
This question already has answers here:
Sort JavaScript object by key
(37 answers)
Closed 3 months ago.
Suppose I have the following array:
var sample: [{
pin_code: "110015",
city: "New Delhi",
address: "xyz",
}]
I want the output as:
var sample: [{
address: "xyz",
city: "New Delhi",
pin_code: "110015",
}] // arranging the keys alphabetically
I wrote a function that gets the total keys and inserts it in a new object then returns the object if you don't understand anything let me know in the comments I'll explain!
var sample= [{
pin_code: "110015",
city: "New Delhi",
address: "xyz",
},{
pin_code: "110015",
city: "New Delhi",
address: "xyz",
}]
const sort_keys = (obj) =>{
const new_ordered_sample = []
const keys= []
obj.map((o,i) => {
keys[i] = [];
Object.keys(o).map((v, j)=>keys[i].push(v))
let newObj = {};
keys[i].sort().map((e)=>{
newObj[e] = obj[i][e]
})
new_ordered_sample.push(newObj)
})
return (new_ordered_sample)
}
sample = sort_keys(sample)
console.log(sample)
PS: Tested and working! you can edit the sample and add as many objects as you want!
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
thanks for taking a look at this. Sorry for length, trying to be clear!
WHAT I'M TRYING TO DO:
I have an array of users (each user an object) and am trying to filter the users on multiple criteria ("males from France" OR "females from Spain and United States with Engineering skills" etc) but it's proven beyond my skills so far.
The hard part has been that the users are objects within a User array, but within each user object, some values are additional objects or arrays. Here's what the user data array looks like (abbreviated):
let users = [
{
gender: 'male',
location: {street: 'Clement Street', country: 'United States'},
skills: ['engineering', 'underwater'],
}, ...
Notice gender is just a normal property/value but country is within a location object and skills are within an array.
I already have a search button interface that creates toggle buttons to search on each criteria available, and every time you click a button, I add or remove that criteria in a filter object. The filter object looks like this, and uses arrays inside it so that I can define multiple criteria at once, like multiple countries to search, multiple skills, etc.:
filter: {
gender: ['female'],
location: {
country: ['Spain'],},
skills: ['optics', ]
},
WHERE I REALLY GET STUCK
I've created a filterData method that can successfully filter based on Gender (male or female) but can't get it to ALSO filter on country (within the location object) or skills (within the skills array). My current filterData method only goes through one iteration per user, but I've tried For loops and forEach to try to go through each of the filter's criteria ('Spain', 'Optics'), but it just doesn't work. I only get gender.
I think I have two problems: 1) somehow conveying in the code that the item 'key' in some cases will not be a value, but an object or array that must also be searched within, and 2) creating some kind of looping behavior that will go through each of the filter criteria, instead of stopping after the first one (gender).
That's apparently over my head right now, so any guidance or suggestions would be appreciated, thanks very much! And here's all the code I've been working with, including my filterData method.
var filtering = {
filter: {
gender: ["female"],
location: {
country: ["Spain"],
},
skills: ["optics"],
},
users: [
{
gender: "male",
name: "John",
location: { street: "Clement Street", country: "United States" },
skills: ["engineering", "underwater"],
},
{
gender: "female",
name: "Mary",
location: { street: "5th Avenue", country: "Spain" },
skills: ["confidence", "optics"],
},
{
gender: "male",
name: "David",
location: { street: "Vermont Ave", country: "France" },
skills: ["cards", "metalurgy", "confidence"],
},
{
gender: "female",
name: "Rachel",
location: { street: "Vermont Ave", country: "France" },
skills: ["disguise", "electrical"],
},
{
gender: "female",
name: "Muriel",
location: { street: "Vermont Ave", country: "Germany" },
skills: ["flight", "surveillance"],
},
],
filterData: (filter) => {
const filteredData = filtering.users.filter((item) => {
for (let key in filter) {
if (!filter[key].includes(item[key])) {
return false;
}
return true;
}
});
console.log(filteredData);
},
};
filtering.filterData(filtering.filter);
There's a nifty trick called recursion, which is a function calling itself.
The updated code are: checkUserand
filterData
var filtering = {
filter: {
gender: ["female"],
location: {
country: ["Spain"],
},
skills: ["optics"],
},
users: [
{
gender: "male",
name: "John",
location: { street: "Clement Street", country: "United States" },
skills: ["engineering", "underwater"],
},
{
gender: "female",
name: "Mary",
location: { street: "5th Avenue", country: "Spain" },
skills: ["confidence", "optics"],
},
{
gender: "male",
name: "David",
location: { street: "Vermont Ave", country: "France" },
skills: ["cards", "metalurgy", "confidence"],
},
{
gender: "female",
name: "Rachel",
location: { street: "Vermont Ave", country: "France" },
skills: ["disguise", "electrical"],
},
{
gender: "female",
name: "Muriel",
location: { street: "Vermont Ave", country: "Germany" },
skills: ["flight", "surveillance"],
},
],
checkUser (filter, to_check) {
if (Array.isArray(filter))
{
return Array.isArray(to_check)
? filter.some(val => to_check.includes(val)) // if what we're checking is an array
: filter.includes(to_check); // otherwise it's a singular value
}
else
{
const all_checks = []; // this is to save every return value from the recursive function
for (let key in filter) // going through each key in the filter
{
const checked = this.checkUser(filter[key], to_check[key]) // passing two values, which will be compared with each other
all_checks.push(checked) // pushing the checked result
}
return all_checks.every(val => val) // checking that it passes the filter by ensuring every value is true
}
},
filterData () {
let filter = this.filter
return this.users.filter(user => this.checkUser(filter, user))
},
};
// filtering.filterData(filtering.filter);
// filtering.checkUser(filtering.filter, filtering.users[0])
const result = filtering.filterData()
console.log(result)
Bit complex data structure, you should clean. However, solved what expected.
const mergeFilter = (item, [key, value]) => {
let val = Array.isArray(item[key]) ? item[key] : [item[key]];
let m = value[0];
if (typeof value === "object" && !Array.isArray(value)) {
const k2 = Object.keys(value);
val = item[key][k2];
m = value[k2][0];
}
return val.includes(m);
};
const filterData = (users, filter) => {
const filters = Object.entries(filter);
const result = users.reduce((arr, item) => {
let found = filters.every(mergeFilter.bind(null, item));
if (found) arr.push(item);
return arr;
}, []);
return result;
};
var filtering = {"filter":{"gender":["female"],"location":{"country":["Spain"]},"skills":["optics"]},"users":[{"gender":"male","name":"John","location":{"street":"Clement Street","country":"United States"},"skills":["engineering","underwater"]},{"gender":"female","name":"Mary","location":{"street":"5th Avenue","country":"Spain"},"skills":["confidence","optics"]},{"gender":"male","name":"David","location":{"street":"Vermont Ave","country":"France"},"skills":["cards","metalurgy","confidence"]},{"gender":"female","name":"Rachel","location":{"street":"Vermont Ave","country":"France"},"skills":["disguise","electrical"]},{"gender":"female","name":"Muriel","location":{"street":"Vermont Ave","country":"Germany"},"skills":["flight","surveillance"]}]}
const result = filterData(filtering.users, filtering.filter);
console.log(result)
Closed. This question needs to be more focused. It is not currently accepting answers.
Want to improve this question? Update the question so it focuses on one problem only by editing this post.
Closed 4 years ago.
Improve this question
I have feature in my application that should allow users to select items in drop down menu and move them up and down. Once they select and click on the button I have to loop over the array of objects and pull only records that were selected in drop down menu. Here is example of my code:
var selectedColumns = ['first','last','city'];
var data = [
{
first: "Mike",
last: "Ross",
dob: "05/26/1978",
city: "Washington DC",
state: "DC",
zip: 22904
},
{
first: "John",
last: "Henderson",
dob: "11/06/1988",
city: "Iowa City",
state: "IA",
zip: 52401
},
{
first: "Nina",
last: "Barkley",
dob: "01/16/1968",
city: "New York",
state: "NY",
zip: 11308
},
{
first: "Jessie",
last: "Kuch",
dob: "02/02/1956",
city: "Des Moines",
state: "IA",
zip: 55432
},
{
first: "Jenny",
last: "Terry",
dob: "012/28/1988",
city: "Miami",
state: "FL",
zip: 83943
}
]
In selected column we only have first, last and city. Then I have to loop over data and pull only selected columns. One way to do that is like this:
for(var key in data){
for(var i=0; i<selectedColumns.lenght; i++){
var columnID = String(columns[i]);
console.log($.trim(data[key][columnID]));
}
}
While this solution works just fine, I'm wondering if there is better way to avoid inner loop and improve efficiency? I use JQuery/JavaScript in my project. If anyone knows a better way to approach this problem please let me know. Thank you.
You can use Array.map, Array.reduce and Object.assign
var selectedColumns = ['first','last','city'];
var data = [{first: "Mike",last: "Ross",dob: "05/26/1978",city: "Washington DC",state: "DC",zip: 22904},{first: "John",last: "Henderson",dob: "11/06/1988",city: "Iowa City",state: "IA",zip: 52401},{first: "Nina",last: "Barkley",dob: "01/16/1968",city: "New York",state: "NY",zip: 11308},{first: "Jessie",last: "Kuch",dob: "02/02/1956",city: "Des Moines",state: "IA",zip: 55432},{first: "Jenny",last: "Terry",dob: "012/28/1988",city: "Miami",state: "FL",zip: 83943}];
let result = data.map(o => selectedColumns.reduce((a,c) => Object.assign(a,{[c]:o[c]}), {}));
console.log(result);
EDIT
var selectedColumns = ['dob','last','city'];
var data = [{first: "Mike",last: "Ross",dob: "01/01/1900",city: "Washington DC",state: "DC",zip: 22904},{first: "John",last: "Henderson",dob: "11/06/1988",city: "Iowa City",state: "IA",zip: 52401},{first: "Nina",last: "Barkley",dob: "01/16/1968",city: "New York",state: "NY",zip: 11308},{first: "Jessie",last: "Kuch",dob: "02/02/1956",city: "Des Moines",state: "IA",zip: 55432},{first: "Jenny",last: "Terry",dob: "012/28/1988",city: "Miami",state: "FL",zip: 83943}];
let result = data.map(o => selectedColumns.reduce((a,c) => {
if(c === 'dob' && o[c] === '01/01/1900') a[c] = 'N/A';
else a[c] = o[c];
return a;
}, {}));
console.log(result);
Another important thing to mention is that it's generally a bad idea to use for ... in construct to iterate over array items in JavaScript (see Why is using "for...in" with array iteration a bad idea? for some explanations).
Just a single line of code by mapping the wanted properties.
Array#map for getting a new array of data and for mapping the wanted keys as new objects witk
computed property names and the value, assigned to a single object with
Object.assign and
spread syntax ... for taking an array as arguments.
var selectedColumns = ['first','last','city'],
data = [{ first: "Mike", last: "Ross", dob: "05/26/1978", city: "Washington DC", state: "DC", zip: 22904 }, { first: "John", last: "Henderson", dob: "11/06/1988", city: "Iowa City", state: "IA", zip: 52401 }, { first: "Nina", last: "Barkley", dob: "01/16/1968", city: "New York", state: "NY", zip: 11308 }, { first: "Jessie", last: "Kuch", dob: "02/02/1956", city: "Des Moines", state: "IA", zip: 55432 }, { first: "Jenny", last: "Terry", dob: "012/28/1988", city: "Miami", state: "FL", zip: 83943 }],
result = data.map(o => Object.assign(...selectedColumns.map(k => ({ [k]: o[k] }))));
console.log(result);
.as-console-wrapper { max-height: 100% !important; top: 0; }
You will find Array.filter suits this use-case
var words = ['spray', 'limit', 'elite', 'exuberant', 'destruction', 'present'];
const result = words.filter(word => {
return word.length > 6;
});
console.log(result);
// expected output: Array ["exuberant", "destruction", "present"]
You could look into using filters where you build the filtering method based on the search criteria and return the filtered array.
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/filter
const newArr = oldArr.filter(record => record.first === 'Nina')
//newArr would only have Nina's record
alternatively if you are trying to go by having a particular field you can still use filter as well
var newArr2 = data.filter(record => record.hasOwnProperty('first'))
// newArr2 would have all records with the property name
I am meeting now the difficult problem for me that hurt my heart,
I want to convert [01] JSON to [02].
[01] JSON :
{locations: [
{
country: "Australia",
area: "NSW",
city: "Gordon"
},
{
country: "Australia",
area: "NSW",
city: "Chatswood"
}
]};
[02] JSON :
{countries: [
{
name: "Australia",
areas: [
{
name: "NSW",
cities: [
{
name: "Gordon"
},
{
name: "Chatswood"
}
]
}
]
}
]}
Since you're going to be doing a bunch of lookups I suggest using a collection of objects rather than your final structure with arrays. You can then either convert it to the final structure or modify code to use it the way it is.
var countries = {};
for (var i=0, loc; loc = locations[i]; i++) {
if (!countries[loc.country]) countries[loc.country] = {};
if (!countries[loc.country][loc.area]) countries[loc.country][loc.area] = [];
countries[loc.country][loc.area].push(loc.city);
}
alert(JSON.stringify(countries));