Filter JSON with unique key/values - javascript

I have a JSON object structured as such:
var theSchools = {
Bradley University: "bru",
Knox College: "knox",
Southern Illinois University Edwardsville: "siue",…
}
What I am trying to achieve is a way of retrieving the key, in this case the school name, by supplying the value, the schools 'code.'
It does not appear that I will be able to have this restructured correctly, i.e.
var theSchools = [
{
schoolName:"Bradley University",
schoolCode: "bru"
}
{
schoolName: "Knox College",
schoolCode: "knox"
}
]
so I'm kind of stuck with what I got.
I know the following code is incorrect, but it's essentially what I want to achieve:
if(getParameterByName("schoolId").length>0){
var schoolid = getParameterByName("schoolId");
var schoolName= theSchools.schoolid;
jQuery("h1").after("<h2>Welcome to <strong>"+schoolName+"</strong></h2>")
}

You can use a for...in loop to loop over each property in the object, and return the property name if the value matches:
var theSchools = {
"Bradley University": "bru",
"Knox College": "knox",
"Southern Illinois University Edwardsville": "siue"
};
function findSchool(code) {
for (var s in theSchools) {
if (theSchools[s] === code)
return s;
}
return null;
}
document.getElementById('school').innerText = findSchool('knox');
<div id="school"></div>

The question is if you really need it this way (see answer #James), here's what you requested:
var theSchools = {
"Bradley University": "bru",
"Knox College": "knox",
"Southern Illinois University Edwardsville": "siue"
}, schoolMap = {};
for (var schoolName in theSchools) {
var code = theSchools[ schoolName ];
schoolMap[ code ] = schoolName;
}
document.body.innerHTML = schoolMap["bru"]; // Bradley University

You don't have to use a for loop to check if property exists. Use hasOwnProperty method.
if (theSchools.hasOwnProperty("Knox College")) {
//do stuff
}
Working example: https://jsfiddle.net/7q9czdpc/

Related

How to store arrays of data in object using JavaScript

how to store arrays of data in an Object. I tried to store data using
var namelist = [], labelDetails = {};
addedLabels_list.push(name);
labedDetails_list[ownerName] = Address;
namelist holds unique names while labelDetails store data in key value pair
Namelist :
0:"ahmad"
1:"jhon"
2: "hamza"
3: "emma"
labelDetails :
ahmad :"lahore"
jhon :"USA"
hamza :"UK"
emma :"USA, Calforina"
But when same owner name has multiple addresses it won't work.
Let's say Emma live in USA, California and her second address is Washington Dc
and it replaces emma :"washington dc"
var namelist = [], labelDetails = {};
addedLabels_list.push(name);
labedDetails_list[ownerName] = Address;
I would try designing a data structure that also stays stable over time, thus choosing a name based (better id based) key-value person-registry that for each person refers a single data item. This data node then is the root for all person related data that yet will come and then has to be taken care of as well ...
var personRegistry = {
ahmad: {
addressList: ["Lahore"]
},
jhon: {
addressList: ["USA"]
},
hamza: {
addressList: ["UK"]
},
emma: {
addressList: ["USA, California"]
}
}
function storeAddress(name, address) {
var store = personRegistry[name];
if (!store) {
store = personRegistry[name] = {};
store.addressList = [];
}
// prevent address duplicates ...
//if (!store.addressList.includes(address)) { // use that if available.
if (store.addressList.indexOf(address) < 0) {
store.addressList.push(address);
}
}
console.log('personRegistry : ', personRegistry);
storeAddress("emma", 'USA, California');
storeAddress("emma", 'USA, Washington DC');
storeAddress("emma", 'USA, Washington DC');
storeAddress("susan", 'Canada, Toronto');
storeAddress("susan", 'Canada, Toronto');
console.log('personRegistry : ', personRegistry);
.as-console-wrapper { max-height: 100%!important; top: 0; }
For arrays, the key should be unique, so in this case, you can use array to store multiple address for a the same key, this is a start :
function myFunction(){
var namelist = ["ahmad", "jhon", "hamza", "emma"],
labelDetails = {ahmad :["lahore"], jhon :["USA"], hamza :["UK"], emma :["USA, Calforina"]};
labelDetails["emma"].push("washington dc");
console.log(labelDetails);
}
<button onclick="javascript:myFunction()">Click me</button>
You definitely have to make some changes to make your solution work, I would suggest,
labelDetails = {
"ahmad" : ["lahore"],
"jhon" : ["USA"],
"hamza" : ["UK"],
"emma" : ["USA, Calforina"]
};
labelDetails[ownerName].push("washington dc");

Push Arrays' indexes into one object

How to push array indexes into one object where the correspondence between {key:value} in my example would be {authors[i]: quotes[i]}?
Please check my codepen:
http://codepen.io/anon/pen/Ndezeo
Thanks.
You could iterate authors and take the name as key and assign the item of quotes as property of the object.
var quotes = [],
authors = [],
object = {};
quotes[0] = "I have a new philosophy. I'm only going to dread one day at a time.";
authors[0] = "Charles Schulz";
quotes[1] = "Reality is the leading cause of stress for those in touch with it.";
authors[1] = "Jack Wagner";
quotes[2] = "Few things are harder to put up with than the annoyance of a good example.";
authors[2] = "Mark Twain";
quotes[3] = "The pure and simple truth is rarely pure and never simple.";
authors[3] = "Oscar Wilde";
quotes[4] = "There's no business like show business, but there are several businesses like accounting.";
authors[4] = "David Letterman";
quotes[5] = "Man invented language to satisfy his deep need to complain.";
authors[5] = "Lily Tomlin";
authors.forEach(function (k, i) {
object[k] = quotes[i];
});
console.log(object);
The answer to your question would be:
var combined = [];
for (var i = 0; i < quotes.length; i++) {
combined[authors[i]] = quotes[i]
}
console.log(combined);
But the really simple and elegant solution here would be to place all your values in a single array from the start:
var quotes = [
{
author: "Charles Schulz",
quote: "I have a new philosophy. I'm only going to dread one day at a time."
},
{
author: "Jack Wagner",
quote: "Reality is the leading cause of stress for those in touch with it."
}
/* etc... */
];
Than you can go over your quotes array with a simple for:
console.log(quotes);
for (var i = 0; i < quotes.length; i++) {
/* access each object like this:
quotes[i].author;
quotes[i].quote;
*/
}
Alternatively, depending on your needs you could structure your data in an object, with this structure:
quotes = {
"Charles Schulz":"I have a new philosophy. I'm only going to dread one day at a time.",
"Jack Wagner":"Reality is the leading cause of stress for those in touch with it."
/* etc... */
}
You can use the for...of loop and ES6 destructing or Array#reduce to build a new object.
let quotes = [];
let authors = [];
let object = {};
quotes[0] = "I have a new philosophy. I'm only going to dread one day at a time.";
authors[0] = "Charles Schulz";
quotes[1] = "Reality is the leading cause of stress for those in touch with it.";
authors[1] = "Jack Wagner";
quotes[2] = "Few things are harder to put up with than the annoyance of a good example.";
authors[2] = "Mark Twain";
quotes[3] = "The pure and simple truth is rarely pure and never simple.";
authors[3] = "Oscar Wilde";
quotes[4] = "There's no business like show business, but there are several businesses like accounting.";
authors[4] = "David Letterman";
quotes[5] = "Man invented language to satisfy his deep need to complain.";
authors[5] = "Lily Tomlin";
// for...of loop taking advantage of the new array method entries & using destructuring
for (const [index, element] of authors.entries()) {
if (!object[element])
object[element] = quotes[index];
}
console.log('Result of using for...of loop:', object);
// array method reduce: Setting an object as the initial value
const usingReduce = authors.reduce((obj, author, index) => {
if (!obj[author])
obj[author] = quotes[index];
return obj; // always return initial value
}, {}); // here I set an obj as the initial value
console.log('Result of using Array#reduce: ', usingReduce);
// using map to return an object containing the authors
// { author: author } same key/value pairs can be shortened to -> { author }
const usingMap = authors.map((author, index, authorsArray) => ({
author,
quote: quotes[index]
}));
console.log('Result of using Array#map method: ', usingMap);

Iterating through dictionary inside class object in JavaScript

I have a class:
class Quizer {
// construct new quiz for unique user
constructor(quizObj) {
this.quiz = quizObj;
this.currentQuestionNum = 0;
this.userSelections = [];
}
...
buttonAction(setup) {
//var text = this.quiz.question1.question; <-- //works
var text = this.quiz[currentQuestionNum].question; // doesnt work
}
}
That is constructed here:
var quiz = new Quizer(questionObjects);
Where questionObjects is:
var questionObjects = {
question1: {
question: "Darwin explained his theory of evolution in a book called?",
choices: [
"this is the correct answer, choose me!",
"On the Origin of Species",
"Survival of the Fittest"
],
correctAnswer: "On the Origin of Species"
},
question2: {
...
}
}
In buttonAction, my goal is to iterate through questionObjects and get each question. Can someone help me with the syntax?
You need something like this
for(var key in questionObjects){
// The following gives you the question for the current key
questionsObjects[key].question
}
As it is stated here:
The for...in statement iterates over the enumerable properties of an
object, in arbitrary order. For each distinct property, statements can
be executed.

Finding object in nested collection with Underscore.js

I have a collection of teams (in a league) like so:
var fra1 = {
"sports":[
{
"name":"soccer",
"id":600,
"uid":"s:600",
"leagues":[
{
"name":"French Ligue 1",
"abbreviation":"fra.1",
"id":710,
"isTournament":false,
"country":{
"id":7,
"name":"France",
"abbreviation":"FRA"
},
"uid":"s:600~l:710",
"groupId":9,
"shortName":"Ligue 1",
"teams":[
{
"id":159,
"uid":"s:600~t:159",
"location":"Bordeaux",
"name":"Bordeaux",
"nickname":"Bordeaux",
"abbreviation":"BOR",
"color":"00003e",
},
{
"id":160,
"uid":"s:600~t:160",
"location":"Paris Saint-Germain ",
"name":"Paris Saint-Germain ",
"nickname":"Paris Saint-Germain ",
"abbreviation":"PSG",
"color":"000040",
}
]
}
]
}
],
}
There are about 20 teams in each var stored in this way. Then, I have about six such leagues: eng1, esp1, fra1, ger1, ita1, and usa1. I put those in another collection, like so:
var all = {
"eng1":eng1,
"esp1":esp1,
"fra1":fra1,
"ger1":ger1,
"ita1":ita1,
"usa1":usa1
}
Now, each team (regardless of the league they're in) has a unique ID: in the above example, Bordeaux has ID 159, PSG has ID 160, and so on. So I want to be able to search the all collection for a unique team by teamid, using Underscore.js, but I can't quite get the syntax down. I know I could search one league like so:
var obj = _.find(fra1.sports[0].leagues[0].teams, function(obj) { return obj.id == teamid })
But I can't figure out how to do it across all six leagues. Can anyone help? I'd prefer not to have to combine the collections into one manually, that would be cumbersome with the amount of data involved.
EDIT: I'm currently using:
for (var league in all)
{
var obj = _.find(all[league].sports[0].leagues[0].teams, function(obj) { return obj.id == teamid })
if (obj !== undefined)
{
// do things
}
}
But would still like something nicer.
One solution would be to create a map of the teams with the team id as the key and the team as the value:
var teams = {};
_.each(all, function(nation){
_.each(nation.sports[0].leagues[0].teams, function(team){
teams[team.id] = team;
});
});
You could then access the team using the key:
var psg = teams[160];
As far as parsing the rest of the teams, just use chain:
var allTeams = _.chain(all)
.values()
.pluck('sports').flatten() // once
.pluck('leagues').flatten() // twice
.pluck('teams').flatten() // third time's a charm
.value()
I would recommend using _.groupBy() on teamID. This will give you a hash-table (JS object) that maps teamID -> teamObject. Say you have your teams parsed like this:
var allTeams =[
{
"id":159,
"uid":"s:600~t:159",
"location":"Bordeaux",
"name":"Bordeaux",
"nickname":"Bordeaux",
"abbreviation":"BOR",
"color":"00003e",
},{
"id":160,
"uid":"s:600~t:160",
"location":"Paris Saint-Germain ",
"name":"Paris Saint-Germain ",
"nickname":"Paris Saint-Germain ",
"abbreviation":"PSG",
"color":"000040",
}]
You can group them with:
var lookup = _.groupBy(teams, 'id')
And then look up a team like this:
var myTeam = lookup[teamId]
Simply do additional loops over the sports and leagues, not only over all:
for (var league in all) {
var sports = all[league];
for (var i=0; i<sports.length; i++) {
var leagues = sports[i].leagues;
for (var j=0; j<leagues.length; j++) {
var teams = leagues[j].teams;
// var obj = _.find(teams, function(obj) { return obj.id == teamid })
for (var k=0; k<teams.length; k++) {
var obj = teams[k];
if (obj.id == teamid) {
… // do things
}
}
}
}
}

javascript find in array

I have an array like this:
var movies = [
{ Name: "The Red Violin", ReleaseYear: "1998", Director: "François Girard" },
{ Name: "Eyes Wide Shut", ReleaseYear: "1999", Director: "Stanley Kubrick" },
{ Name: "The Inheritance", ReleaseYear: "1976", Director: "Mauro Bolognini" }
];
I want to find the location of the movie that's released in 1999.
Should return 1.
What's the easiest way?
Thanks.
You will have to iterate through each value and check.
for(var i = 0; i < movies.length; i++) {
if (movies[i].ReleaseYear === "1999") {
// i is the index
}
}
Since JavaScript has recently added support for most common collection operations and this is clearly a filter operation on a collection, instead you could also do:
var moviesReleasedIn1999 = movies.filter(function(movie) {
return movie.ReleaseYear == "1999";
});
assuming you're not interested in the indexes but the actual data objects. Most people aren't anyways :)
.filter is not supported in all browsers, but you can add it yourself to your code base:
https://developer.mozilla.org/en/JavaScript/Reference/Global_Objects/Array/filter#Compatibility
Built in? Use loops.
You want to get fancy? Linq to Javascript: http://jslinq.codeplex.com/
Something like:
function findMovieIndices(movies, prop, value) {
var result = [];
for(var i = movies.length; i--; ) {
if(movies[i][prop] === value) {
result.push(i); // personally I would return the movie objects
}
}
return result;
}
Usage:
var indices = findMovieIndices(movies, "ReleaseYear", "1999");
Maybe this gives you some idea for a more generalized function (if you need it).
Since you've also tagged it with jQuery, you could use the 'map' function:
var movies = $.map(movies,function(item,index){
return item.ReleaseYear == 1999 ? index : null;
});
This will return an array of indexes for all movies with the year of 1999. If you wanted the movies themselves as an array:
var movies = $.map(movies,function(item){
return item.ReleaseYear == 1999 ? item : null;
});
If functional style programming is applicable:
_.indexOf(_.pluck(movies, "ReleaseYear"), "1999")
Because it's that simple. The functional toolkit that is underscore.js can be very powerful.
_.indexOf , ._pluck
You'll have to create your own searching function.
Array.prototype.findMovieByYear = function (findYear) {
for (var i = 0; i < this.length; i++) {
// this actually returns the element, maybe you just want
// to return the array index ( the i param )
if (this[i].Release == findYear) return this[i];
}
return null;
// or return -1 or whatever if you want to return the index
};
// now you can call:
movies.findMovieByYear('1998');
// and that should return
{ Name: "The Red Violin", ReleaseYear: "1998", Director: "François Girard" }
Of course, this way of doing it actually affects every array you create.. which is maybe not what you want.. you can create your own array object then ...

Categories