I am looking for some general advice about how I should be thinking to go about doing this.
What I need to do is take an object that has "usernames" : userId, etc.. and split them into separate objects or arrays with each object only containing usernames that start from a certain letter.
So right now I have:
allusers = {"adam292":10302, "alex92":12902, "briannv999":10302, "sandra127":11102, "sam11":100 }
but I need to split them into their own objects or arrays like the following:
ausers = { "adam292":10302, "alex92":12902 }
busers = { "briannv999":10302 }
susers = {"sandra127":11102, "sam11":1002 }
I am doing this because I need to display a dialog box that also shows the letters a - z which would be links that you can click to display users that start with that letter.
Any advice is very much appreciated!
Here is one way to do it:
Working Fiddle
looping through the object we grab the first letter and check to see if we have a key for it in our users object, if not we make one and assign an array (containing the user data) to it, if yes we push to that array:
var users = {};
for (var user in allusers) {
var firstLetter = user.slice(0,1);
if (users[firstLetter]) {
users[firstLetter].push([user, allusers[user]]);
}
else {
users[firstLetter] = [[user, allusers[user]]];
}
}
The output of the code above using your example object is the following:
{
a: [["adam292", 10302], ["alex92", 12902]],
b: [["briannv999", 10302]],
s: [["sandra127", 11102], ["sam11", 100]]
}
you can do this in a loop:
letter2users = {}
for (var uname in allusers) {
if (!letter2users[uname[0]]) {
letter2users[uname[0]] = [];
}
letter2users[uname[0]].push(allusers[uname]);
}
# access this by using letter2users.a lettersusers.b
Related
I just need to merge two files with the same list, but with different values on each file. Preferably in JavaScript
For example:
File 1
{"list1":{"a":1,"b":2}
{"list2":{"c":3,"d":4}
File 2
{"list1":{"a":5,"b":6}
{"list2":{"c":7,"d":8}
The desired result is
{"list1":{"a":6,"b":8}
{"list2":{"c":10,"d":12}
Sorry for the noob question, but the person who sent me the files should have done this themselves, but are currently unavailable. The files are too big to do by hand.
This is not very flexible code, but it would be far more work, to make something more dynamic. You would have to parse the objects recursevely and check if the property is an object and then jump deeper. Until ou find the values.
And please be aware that I'm not making any type checking whatsoever. If the data contains faulty data it is not cought properly. Also this code requires this exact structure. If your object contains other properties it might crash too.
// your data
const f1l1 = '{"list1":{"a":1,"b":2}}';
const f1l2 = '{"list2":{"c":3,"d":4}}';
const f2l1 = '{"list1":{"a":5,"b":6}}';
const f2l2 = '{"list2":{"c":7,"d":8}}';
var result1= JSON.parse(f1l1);
var result2= JSON.parse(f1l2);
//the names of the list as they appear in your real data *must* be the first object
const nameList1 = Object.keys(result1)[0];
const nameList2 = Object.keys(result2)[0];
//remove the list name
result1=result1[nameList1];
result2= result2[nameList2];
//get data from other file nd remove list name
const file2List1= JSON.parse(f2l1)[nameList1];
const file2List2= JSON.parse(f2l2)[nameList2];
// go through all items and sum them if the value is already in the list, else put it in for list1
for (var prop in file2List1) {
if (Object.prototype.hasOwnProperty.call(file2List1, prop)) {
if(Object.prototype.hasOwnProperty.call(result1, prop)){
result1[prop] = result1[prop] + file2List1[prop];
}else{
result1[prop] = file2List1[prop];
}
}
}
// and now for list2
for (var prop in file2List2) {
if (Object.prototype.hasOwnProperty.call(file2List2, prop)) {
if(Object.prototype.hasOwnProperty.call(result2, prop)){
result2[prop] = result2[prop] + file2List2[prop];
}else{
result2[prop] = file2List2[prop];
}
}
}
//put names of lists back in.
result1 = {[nameList1]:result1};
result2 = {[nameList2]:result2};
//check results:
console.log("input data:");
console.log(JSON.parse(f1l1));
console.log(JSON.parse(f1l2));
console.log(JSON.parse(f2l1));
console.log(JSON.parse(f2l2));
console.log("output data:");
console.log(result1);
console.log(result2);
You can try this out
newList = list1.concat(list2);
How to split an object into array of objects based on a condition.
oldObject = {"Chicago, IL:Myrtle Beach, SC": 0.005340186908091907,
"Portsmouth, NH:Rock Hill, SC": 0.0063224791225441205,
"Columbia, SC:Laconia, NH": 0.006360767389277389,
"Council Bluffs, IA:Derry, NH": 0.0016636141225441225}
Above is the given sample object. I want to make an array of objects like this,
newArray = [{"city":"Chicago", "similarTo":"Myrtle"},
{"city":"Portsmouth", "similarTo":"Rock Hill"},
{"city":"Columbia", "similarTo":"Laconia"},
{"city":"Council Bluffs", "similarTo":"Derry"}]
I have been scratching my head with this for a while now. How can I get the above array(newArray)?
Here is a bunch of code you can try.
1) Iterate over oldObject and get the name of the property.
2) Split that name into an array based on the ":" character, since it separates the cities
3) Go over that new array, splitting it on the "," character (so as not to get the states).
4) Put the values into the newObject, based on whether it's the first or second part of the original property name.
5) Push that newObject, now with items, into a newArray.
Basically, this parses apart the name and does some array splitting to get at the right values. Hope it helps and helps you understand too.
var oldObject = {"Chicago, IL:Myrtle Beach, SC": 0.005340186908091907,
"Portsmouth, NH:Rock Hill, SC": 0.0063224791225441205,
"Columbia, SC:Laconia, NH": 0.006360767389277389,
"Council Bluffs, IA:Derry, NH": 0.0016636141225441225};
var newArray = [];
for (object in oldObject) {
var thisObjectName = object;
var thisObjectAsArray = thisObjectName.split(':');
var newObject = {
'city': '',
'similar_to': ''
};
thisObjectAsArray.forEach(function(element,index,array) {
var thisObjectNameAsArray = element.split(',');
var thisObjectNameCity = thisObjectNameAsArray[0];
if(index===0) {
newObject.city = thisObjectNameCity;
} else if(index===1) {
newObject.similar_to = thisObjectNameCity;
}
});
newArray.push(newObject);
}
console.log(newArray);
PS: to test, run the above code and check your Developer Tools console to see the new array output.
Hi there before I start I did try looking through the search about writing variables so if this has been asked and answered then I do apologise but this is baffling me ....
So here goes ..
example of what I am talking about
var i = e[ab]
var n = e[cd][ef]
var t = e[cd][gh]
I know that when I want var i I can put e.ab but how would I go about writing var n and var t
So assuming your object looks like this (based on your description, it sounds like you want to access an object which is the property of another object), and you want to access them through the indexer properties (which would be a property of a property).
var e = {
ab : "variableOne",
cd : {ef:"ef object"},
gh : {ij:"ij object"},
}
var i = e["ab"]
//if these are properties, then you need to add quotes around them
//to access a property through the indexer, you need a string.
var n = e["cd"]["ef"]
var t = e["gh"]["ij"]
console.log(i);
console.log(n);
console.log(t);
console.log("this does the same thing:")
console.log(e.ab);
console.log(e.cd.ef);
console.log(e.gh.if);
In your example the object would look like
//e is the parameter, but I show it as a variable to show
// it's relation to the object in this example.
e = {
now_playing: {artist:"Bob Seger"; track:"Turn the Page"}}
}
this is different than an array of arrays:
var arr = [
['foo','charlie'],
['yip', 'steve'],
['what', 'bob', 'jane'],
];
console.log(arr[0][0]); //foo
console.log(arr[0][1]); //charlie
console.log(arr[1][0]); //yip
console.log(arr[1][1]); //steve
console.log(arr[2][2]); //jane
https://jsfiddle.net/joo9wfxt/2/
EDIT:
Based on the JSON provided, it looks like parameter e in the function is assigned the value of the item in the array. With your code:
this line will display: "Rock you like a hurricane - Nontas Tzivenis"
$(".song_title .current_show span").html(e.title);
and this line will display: "Rascal Flatts - Life is a Highway".
$(".song_title .current_song span").html(e.np);
If it's not displaying you might want to double check your JQuery selectors. This ".song_title .current_song span" is selecting it by the classes on the element.
I think you are in need of a bit of a refresher on basic JavaScript syntax. Here's how you can assign an "empty object" to a variable, then start to assign values to it's properties:
e = {}
e.ab = {}
e.cd = {}
e.cd.ef = "data"
or you can use the associative array syntax for property access:
e = {}
e["ab"] = {}
e["cd"] = {}
e["cd"]["ef"] = "data"
You see the latter is using the object e like a two-deep associative array. Is that what you are looking to do?
JavaScript is not strongly typed. So an Array "a" could contain objects of different types inside.
var a = [ "a value", [1, 2, 3], function(){ return 5 + 2;}];
var result = a[0]; //get the first item in my array: "a value"
var resultOfIndexedProperty = a[1][0]; //Get the first item of the second item: 1
var resultOfFunc = a[2](); //store the result of the function that is the third item of my array: 7
Hope this helps a little.
This is my JSON, I want to directly get the zipCodes values from the JSON without looping through the JSON. How can I do it?
countries:[
{
name:'India',
states:[{
name:'Orissa',
cities:[{
name:'Sambalpur',
zipCodes:{'768019','768020'}
}]
}]
}
]
I think you are looking for
countries[0].states[0].cities[0].zipCodes
Please note, this works for the above JSON as there is only 1 country in countries array and same as for states and cities. However, if there are more than 1 country, state or city then, you will have to iterate to extract information until and unless you know the exact index.
As this is not an associative array, your option is only to use indexes like this:
countries[x].states[y].cities[0].zipCodes
Where x would be each representation of state in your array, in case, of course, that you have more than one.
Similarly y would be each state in each state in each country, in case you have more of those and you can do the same for cities if you need to.
EDIT:
Here's how you can iterate the array:
for(var c in countries)
{
var name = countries[c].name;
if (name === "CountryIAmLookingFor")
{
var statesList = countries[c].states;
for (var s in statesList)
{
var stateName = statesList[s].name;
.....
}
}
}
You can keep iterating until you find the country, state, and city you need, then extract the zipCodes from there as shown in the previous code snippet.
Without "looping"
You can do this crazy trick (not saying this is the best way, but this way you aren't looping through the JSON):
var myData = { 'Put Your Data': 'HERE' };
function getCodes(name, data) {
var sv = data.match(new RegExp(name+'([\\S\\s]*?}][\\S\\s]*?}])'))[1].match(/zipCodes":\[(.*?)\]/g), r = [];
sv.forEach(function (item) {
item.match(/\d+/g).forEach(function (sub) {
r.push(+sub);
});
});
return r;
}
getCodes('India', JSON.stringify(myData));
If your data is already string, then you don't need the JSON.stringify. The forEach you see isn't actually "looping" through the JSON. It's already extracted the zip codes and the code just adds the zip codes to the array. . This line:
var sv = JSON.stringify(data).match(new RegExp(name+'([\\S\\s]*?}][\\S\\s]*?}])'))[1].match(/zipCodes":\[(.*?)\]/g), r = [];
is what grabs the zip codes, it gets something like:
["zipCodes":["768019","768020"]"]
The next line:
item.match(/\d+/g)
will grab the numbers outputting something like:
["768019", "768020"]
The loop just adds the zip-codes to another array
With looping
You're better off looping through the JSON:
var myData = {}, // Your data
zips = [];
myData.countries.forEach(function(i) {
if (i.name === 'India') {
i.states.forEach(function(j) {
j.cities.forEach(function(l) {
l.zipCodes.forEach(function(m) {
zips.push(m);
});
});
});
}
});
//use "zips" array
PERFORMANCE AND SPEED TESTS
After testing copying an array about 500MB (half a gig) took about 30 seconds. That's a lot. Considering an extremely large JSON would be about ~5MB, looping through a little over 5MB of JSON takes about 0.14 seconds. You should never worry about speed.
Here's my "trick" for avoiding explicit iteration. Let JSON.parse or JSON.stringify do the work for you. If your JSON is in string form, try this:
var array = [];
JSON.parse(jsonString, function (key, value) {
if (key === "zipCodes") {
array = array.concat(value);
}
return value;
});
console.log(array); // all your zipCodes
Suppose your Json is like
countries =[
{
name:'India',
states:[{
name:'Orissa',
cities:[{
name:'Sambalpur',
zipCodes:768019768020
}]
},{
name:'mumbai',
cities:[{
name:'rea',
zipCodes:324243
}]
}]
}
]
So now we use MAP it will give you ZipCode of every cities
countries.map(function(s){
s.states.map(function(c){
c.cities.map(function(z){
console.log(z.zipCodes)
})
})
})
OR
If you use return statement then it will give you 2 array with two zip code as per over JSON
var finalOP = countries.map(function(s){
var Stalist = s.states.map(function(c){
var zip = c.cities.map(function(z){
return z.zipCodes
})
return zip
})
return Stalist
})
console.log(finalOP)
I am trying to build a data structure.
In my limited knowledge, 'hash table' seems to be the way to go. If you think there is an easier way, please suggest it.
I have two, 1-dimensional arrays:-
A[] - contains names of badges (accomplishment)
B[] - contains respective dates those achievements were accomplished from array A[].
An achievement/accomplishment/badge can be accomplished more than one time.
Therefore a sample of the two arrays:-
A['scholar', 'contributor', 'teacher', 'student', 'tumbleweed', 'scholar'.....,'scholar',......]
B['1/2010', '2/2011', '3/2011', '6/2012', '10/2012', '2/2013',......'3/2013',........]
What I want to achieve with my data structure is:-
A list of unique keys (eq:- 'scholar') and all of its existing values (dates in array B[]).
Therefore my final result should be like:-
({'scholar': '1/2010', '2/2013', '3/2013'}), ({'contributor' : ........})..........
This way I can pick out a unique key and then traverse through all its unique values and then use them to plot on x-y grid. (y axis labels being unique badge names, and x axis being dates, sort of a timeline.)
Can anyone guide me how to build such a data structure??
and how do I access the keys from the data structure created.... granted that I don't know how many keys there are and what are their individual values. Assigning of these keys are dynamic, so the number and their names vary.
Your final object structure would look like this:
{
'scholar': [],
'contributor': []
}
To build this, iterate through the names array and build the final result as you go: if the final result contains the key, push the corresponding date on to its value otherwise set a new key to an array containing its corresponding date.
something like:
var resultVal = {};
for(var i = 0; i < names.length; ++i) {
if(resultVal[names[i]]) {
resultVal[names[i]].push(dates[i]);
} else {
resultVal[names[i]] = [dates[i]];
}
}
Accessing the result - iterating through all values:
for(var key in resultVal) {
var dates = resultVal[key];
for(var i = 0; i < dates.length; ++i) {
// you logic here for each date
console.log("resultVal[" + key + "] ==> " + resultVal[key][i]);
}
}
will give results like:
resultVal[scholar] ==> 1/2010
resultVal[scholar] ==> 2/2013
resultVal[scholar] ==> 3/2013
resultVal[contributor] ==> 2/2011
resultVal[teacher] ==> 3/2011
resultVal[student] ==> 6/2012
resultVal[tumbleweed] ==> 10/2012
You can try this...
var A = ['scholar', 'contributor',
'teacher', 'student', 'tumbleweed', 'scholar','scholar'];
var B = ['1/2010', '2/2011',
'3/2011', '6/2012', '10/2012', '2/2013','3/2013'];
var combined = {};
for(var i=0;i<A.length;i++) {
if(combined[A[i]] === undefined) {
combined[A[i]] = [];
}
combined[A[i]].push(B[i]);
}
Then each one of the arrays in combined can be accessed via
combined.scholar[0]
or
combined['scholar'][0]
Note the === when comparing against undefined