Related
I have an array of nested objects:
const array =[
{
"id": 1,
"time": {
"timezone": "2021-09-22T05:36:22.484Z"
"city": "Perth"
"country:: "Australia
"date": "2021/10/10"
}
},
{
"id": 2,
"time": {
"timezone": "2021-10-22T03:25:26.484Z"
"city": ""
"country: "Americas"
"date": "2021/10/10"
}
},
{
"id": 3,
"time": {
"timezone": "2021-09-27T02:43:26.564Z"
"city": ""
"country: ""
"date": "2021/10/10"
}
}];
I want to check each value in the time object to see if there exists an empty string without having to have multiple || statements.
What I have tried using lodash:
if(array.find((k)=> _.isEmpty(k.timezone)) || array.find((k)=> _.isEmpty(k.city)) || array.find((k)=> _.isEmpty(k.country)) || array.find((k)=> _.isEmpty(k.date))) {
//do something
} else {
//do something else
}
This seems to do the trick but trying to find a succinct and cleaner way to do this as there could be more values in the time object, preferably in es6.
Check if .some of the Object.values of any of the time subobjects includes the empty string.
if (array.some(
k => Object.values(k.time).includes('')
)) {
// do something
} else {
// do something else
}
I am fetching data from an api that, sometimes, gives me multiple objects with the same values, or very similar values, which I want to remove.
For example, I might get back:
[
{
"Name": "blah",
"Date": "1992-02-18T00:00:00.000Z",
"Language": "English",
},
{
"Name": "blahzay",
"Date": "1998-02-18T00:00:00.000Z",
"Language": "French",
}, {
"Name": "blah", // same name, no problem
"Date": "1999-02-18T00:00:00.000Z", // different date
"Language": "English", // but same language
},
]
So I want to check that no two objects have a key with the same "Language" value (in this case, "English").
I would like to get the general process of filtering out the entire object if it's "Language" value is duplicated, with the extra issue of not having the same number of objects returned each time. So, allowing for dynamic number of objects in the array.
There is an example here:
Unexpeected result when filtering one object array against two other object arrays
but it's assuming that you have a set number of objects in the array and you are only comparing the contents of those same objects each time.
I would be looking for a way to compare
arrayName[eachObject].Language === "English"
and keep one of the objects but any others (an unknown number of objects) should be filtered out, most probably using .filter() method along with .map().
The below snippets stores the languages that have been encountered in an array. If the current objects language is in the array then it is filtered out. It makes the assumption that the first object encountered with the language is stored.
const objs = [
{
"Name": "blah",
"Date": "1992-02-18T00:00:00.000Z",
"Language": "English",
},
{
"Name": "blahzay",
"Date": "1998-02-18T00:00:00.000Z",
"Language": "French",
}, {
"Name": "blah", // same name, no problem
"Date": "1999-02-18T00:00:00.000Z", // different date
"Language": "English", // but same language
},
],
presentLanguages = [];
let languageIsNotPresent;
const objsFilteredByLanguage = objs.filter(function (o) {
languageIsNotPresent = presentLanguages.indexOf(o.Language) == -1;
presentLanguages.push(o.Language);
return languageIsNotPresent;
});
console.log(objsFilteredByLanguage);
You could take a hash table and filter the array by checking Name and Language.
var array = [{ Name: "blah", Date: "1992-02-18T00:00:00.000Z", Language: "English" }, { Name: "blahzay", Date: "1998-02-18T00:00:00.000Z", Language: "French" }, { Name: "blah", Date: "1999-02-18T00:00:00.000Z", Language: "English" }],
hash = {},
result = array.filter(({ Name, Language }) => {
var key = `${Name}|${Language}`;
if (!hash[key]) return hash[key] = true;
});
console.log(result);
.as-console-wrapper { max-height: 100% !important; top: 0; }
Using Set makes it easy to remove duplicates for as many keys as you like. I tried to be as verbose as possible so that each step was clear.
var objects = [{ "Name": "blah", "Date": "1992-02-18T00:00:00.000Z", "Language": "English", }, { "Name": "blah", "Date": "1998-02-18T00:00:00.000Z", "Language": "French", }, { "Name": "blah", "Date": "1999-02-18T00:00:00.000Z", "Language": "English" }];
function uniqueKeyVals(objects, key) {
const objVals = objects.map(object => object[key]); // ex. ["English", "French", "English"]
return objects.slice(0, new Set(objVals).size); // ex. { "English", "French" }.size = 2
}
function removeKeyDuplicates(objects, keys) {
keys.forEach(key => objects = uniqueKeyVals(objects, key));
return objects;
}
// can also use uniqueKeyVals(key) directly for just one key
console.log("Unique 'Language': \n", removeKeyDuplicates(objects, ["Language"]));
console.log("Unique ['Language', 'Name']: \n", removeKeyDuplicates(objects, ["Language", "Name"]));
I would use the underscore module for JavaScript and the unique function in this scenario. Here is a sample array of data objects:
let data = [{
name: 'blah',
date: Date.now(),
language: "en"
},
{
name: 'noblah',
date: Date.now(),
language: 'es'
},
{
name: 'blah',
date: Date.now(),
language: 'en'
}];
Then we can use the unique function in the underscore library to only return a copy of the data that has unique values associated with the language key:
const result = _.unique(data, 'language');
I want to iterate through this object by creating a function country(state,foods)
if the state and foods exists in the object,it should return me the state name and foods array of that state.First i tried iterating only state by passing argument state in the function using for in still i didn't get the state name and i don't know what should i do to get foods array.
var india = [
{
"state": "karnataka",
"capital": "Bengaluru",
"foods": ["Mysore masala", "Uthhappa", "Bisi Bele Bhaat"]
},
{
"state": "Maharashtra",
"capital": "Mumbai",
"foods": ["vada pav", "puranpoli", "Missal pav"]
},
{
"state": "Tamil nadu",
"capital": "Chennai",
"foods": ["Medu vada", "aapam", "idli sambhar"]
},
{
"state": "Rajasthan",
"capital": "Jaipur",
"foods": ["Ras malai", "Kadka", "Gujia"]
}
];
This is a poor data structure for your use case, so if you expect to need to search this data often, you might consider having state names as properties on an object for O(1) lookup rather than O(n) approach of iterating this array. That being said, this existing structure can be searched in this case using Array.find().
var result = india.find( item => (item.state === this) , searchState);
console.log(result.foods);
for (var i in india)
{
alert(india[i].state);
// do something else with india[i]
}
Or since india is an array:
for (var i = 0; i < india.length; ++i)
{
// same thing
}
When searching if a specific number or string exists in an array you can use Array.indexOf(), example:
if (india[i].foods.indexOf('Kadka') >= 0)
{
alert(india[i].state + " has food Kadka");
}
A function StateHasFood(state, food) could be something like that:
function StateHasFood(state, food)
{
for (var i in india)
if (india[i].state == state)
return india[i].foods.indexOf(food) >= 0;
return false;
}
Of course you can also return the object relative to the state containing its properties, including it's name and full list of foods like you seem to want:
function StateHasFood(state, food)
{
for (var i in india)
if (india[i].state == state)
if (india[i].foods.indexOf(food) >= 0)
return india[i];
return false;
}
Since you just told me to write a function to check if state and capital are present, and that is true then return the capital. I have wrote this for you. Hope it helps :)
var india = [
{
"state": "karnataka",
"capital": "Bengaluru",
"foods": ["Mysore masala", "Uthhappa", "Bisi Bele Bhaat"]
},
{
"state": "Maharashtra",
"capital": "Mumbai",
"foods": ["vada pav", "puranpoli", "Missal pav"]
},
{
"state": "Tamil nadu",
"capital": "Chennai",
"foods": ["Medu vada", "aapam", "idli sambhar"]
},
{
"state": "Rajasthan",
"capital": "Jaipur",
"foods": ["Ras malai", "Kadka", "Gujia"]
}
];
function country(someState , someCapital){
for (var i in india)
{
if(india[i].state === someState && india[i].capital === someCapital){
return india[i].capital;
}
}
}
document.write(country("Tamil nadu", "Chennai"));
From what you've added in the comments, it seems what you really want is a function getPropForState(state, prop) that will return the value of the specified property associated with the specified state. That is, getPropForState("Rajasthan", "foods") would return an array of foods, and getPropForState("Rajasthan", "capital") would return "Jaipur".
Assuming that is the case, perhaps something like the following:
// same array as in question, but with line breaks removed
// so that it doesn't clutter up my answer
var india = [{"state":"karnataka","capital":"Bengaluru","foods":["Mysore masala","Uthhappa","Bisi Bele Bhaat"]},{"state":"Maharashtra","capital":"Mumbai","foods":["vada pav","puranpoli","Missal pav"]},{"state":"Tamil nadu","capital":"Chennai","foods":["Medu vada","aapam","idli sambhar"]},{"state":"Rajasthan","capital":"Jaipur","foods":["Ras malai","Kadka","Gujia"]}];
function getPropForState(state, prop) {
var item = india.find(v => v.state === state);
if (item)
return item[prop];
}
console.log(getPropForState("Rajasthan", "foods")); // returns ["Ras malai","Kadka","Gujia"]
console.log(getPropForState("Rajasthan", "capital")); // returns "Jaipur"
console.log(getPropForState("Maharashtra", "capital")); // returns "Mumbai"
console.log(getPropForState("Maharashtra", "missing")); // returns undefined
console.log(getPropForState("Queensland", "foods")); // returns undefined
Note that if either the state or the specified other property do not exist then the function will return undefined.
Try forEach() method to iterate and Object.keys to get the key:value pairs. Don't completely understand OP's objective so I'll add objArrKey(). This function takes the array and a specific key and return all values associated with said key.
SNIPPET
var India = [{
"state": "karnataka",
"capital": "Bengaluru",
"foods": [
"Mysoremasala",
"Uthhappa",
"BisiBeleBhaat"
]
}, {
"state": "Maharashtra",
"capital": "Mumbai",
"foods": [
"vadapav",
"puranpoli",
"Missalpav"
]
}, {
"state": "Tamilnadu",
"capital": "Chennai",
"foods": [
"Meduvada",
"aapam",
"idlisambhar"
]
}, {
"state": "Rajasthan",
"capital": "Jaipur",
"foods": [
"Rasmalai",
"Kadka",
"Gujia"
]
}]
India.forEach(function(item) {
Object.keys(item).forEach(function(key) {
console.log("key:" + key + " value:" + item[key]);
});
});
function objArrKey(arr, key) {
return arr.map(function(item) {
return item[key] || null;
});
}
console.log(objArrKey(India, ['state']));
console.log(objArrKey(India, ['capital']));
console.log(objArrKey(India, ['foods']));
I need help pushing the values from a filtered json, I need this generate a nested ul list, I can not modify the json format at this point, I you check the console.log you will see the values to create the list, at this point I can't figure how to complete the 'for loop' to render the html markup needed, any help will be appreciated, this is the jsfiddle http://jsfiddle.net/43jh9hzz/, and if you check the console log you will see the values.
This is the Js:
var json='';
var property_set = new Set();
function iterate(obj, stack) {
json="<ul>";
for (var property in obj) {
if (obj.hasOwnProperty(property)) {
if (typeof obj[property] == "object") {
iterate(obj[property], stack + '.' + property);
}
else {
// console.log(property);
property_set.add(property);
json+="<li>";
if(typeof obj[property] !== "number") {
json+="<li>"+obj[property]+"</li>";
console.log(obj[property]);
}
}
} json += "</li>";
}
}
var listEl = document.getElementById('output');
iterate(jsonObj)
And this is the json format:
var jsonObj =
{
"level_1": [
{
"level_1_name": "CiscoSingaporeEBC",
"level_2": [
{
"level_2_name": "Khoo Tech Puat",
"level_2_id": 2222,
"level_3": [
{
"name": "Boon Leong Ong",
"id": 6919
},
{
"name": "Kiat Ho",
"id": 6917
},
{
"name": "Overall Experience",
"id": 6918
}
]
}
]
},
{
"level_1_name": "CiscoLondonEBC",
"level_2": [
{
"level_2_name": "Bernard Mathews Ltd.",
"level_2_id": 2367,
"level_3": [
{
"name": "Barry Pascolutti",
"id": 7193
},
{
"name": "Kathrine Eilersten",
"id": 7194
},
{
"name": "Martin Rowley",
"id": 7189
}
]
},
{
"level_2_name": "FNHW Day 1",
"level_2_id": 5678,
"level_3": [
{
"name": "Jurgen Gosch",
"id": 7834
},
{
"name": "Overall Experience",
"id": 7835
}
]
},
{
"level_2_name": "Groupe Steria Day 1",
"level_2_id": 2789,
"level_3": [
{
"name": "Adam Philpott",
"id": 7919
},
{
"name": "Pranav Kumar",
"id": 7921
},
{
"name": "Steve Simlo",
"id": 7928
}
]
}
]
}
]
};
enter code here
I'm not sure if I am interpretting your request correctly, but I think this is what you want: http://jsfiddle.net/mooreinteractive/43jh9hzz/1/
Basically, you are calling the iterate function to run, but then that's it. The function actually needs to also return the value it generates.
I've added to the end of the function, after the for loop completes:
return json;
Do now the function returns the value it generated, but there are some other issues too. When you recursively call the iterate function again inside the iterate function, you actually want to add what it returns to the current json string housing all of your returned value.
So on that line I changed it from:
iterate(obj[property], stack + '.' + property);
to
json += iterate(obj[property], stack + '.' + property);
Now that other value will come back as well inside the main list you were creating in the first run of the function. Ok so that's pretty close, but one more small thing. I think when you added additional surrounding LI, you actually wanted to do an UL. I changed those to ULs and now I think the result is like a UL/LI list representing the text parts of the JSON object.
Again, that may not be exactly what you were after, but I think the main take away is using the function to return the value, not just generate it, then do nothing with it.
I have to create a column chart in my project using Highchart. I am using $.ajax to populate this data. My current JSON data is like this :
[{
"city": "Tokyo",
"totalA": "10",
"totalB": "15"
},
{
"city": "Seoul",
"totalA": "20",
"totalB": "27"
},
{
"city": "New York",
"totalA": "29",
"totalB": "50"
}]
How to resulting JSON string look like this:
[{
"name": "city",
"data": ["Tokyo", "Seoul", "New York"]
}, {
"name": "totalA",
"data": [10, 20, 29]
}, {
"name": "totalB",
"data": [15, 27, 50]
}]
Thank you.
Assuming all the elements look the same (they all have the same fields): Live Example
// src is the source array
// Get the fields from the first element
var fields = Object.keys(src[0]);
// Map each key to...
var result = fields.map(function(field) {
// Grab data from the original source array
var data = src.reduce(function(result, el) {
// And create an array of data
return result.concat(el[field]);
}, []);
// Format it like you want
return {name: field, data: data};
});
console.log(result);
If they aren't, the code is slightly more complicated: Live Example
// Work out the fields by iterating all of the elements
// and adding the keys that weren't found yet to an array
var fields = src.reduce(function (fields, current) {
return fields.concat(Object.keys(current).filter(function (key) {
return fields.indexOf(key) === -1;
}));
}, []);
var result = fields.map(function (field) {
// Need another step here, filter out the elements
// which don't have the field we care about
var data = src.filter(function (el) {
return !!el[field];
})
// Then continue like in the example above.
.reduce(function (result, el) {
return result.concat(el[field]);
}, []);
return {
name: field,
data: data
};
});
console.log(result);