Say I have:
var Certificated = {}
Sub items are added dynamically and variate. Possible outcome:
var Certificated = {
Elementary: ["foo","bar", "ball"]
MiddleSchool: ["bar", "crampapydime"]
};
I want to do the following:
Certificated.Elementary = Certificated.Elementary.join("");
Except I need it to do that on all of the objects inside.
Keep in mind I can't know for sure the titles of nor how many objects will be inside Certificated.
My question is how can I use .join("") on all elements inside Certificated, without calling each one specifically?
EDIT: I am aware .join() is for arrays and the objects inside Certificated are going to be arrays. Therefore the join method.
Does this work?
for (var key in Certificated) {
if (Certificated.hasOwnProperty(key)) {
Certificated[key] = Certificated[key].join("");
}
}
It loops through all properties of Certificated, and makes a quick safe check for the key being a real property, then uses bracket notation - [""] - to do your join.
Quick question - are you sure you want to use join? I know you just provided an example, but you can't call join on a string...it's for arrays. Just wanted to make sure you knew.
Here's a jsFiddle of my code working with arrays being used for the properties:
http://jsfiddle.net/v48dL/
Notice in the browser console, the properties' values are strings because the join combined them with "".
Related
I have this array
switched = {"Restaurant":1,"Hotel":2,"Beauty shop":3,"Physiotherapist":4,"Dentist":5,"Bar":6,"Coffee shop":7}
and this object
result = [{"Google Place URL":"http://www.restaurant.com","Business Type":"Restaurant"},{"Google Place URL":"http://www.hotel.com","Business Type":"Hotel"}]
I want to validate if every item of the result contains words of switched
also, I'm already working with a for that returns each item separately
item[csvBusinessType] = Restaurant
how can I validate if item[csvBusinessType] is included in switched?
I have tried with
let n = switched.includes(item[csvBusinessType]);
but I get Uncaught TypeError: switched.includes is not a function
There is not good native method for this. Better to use lodash library https://www.npmjs.com/package/lodash
Here is an example
const _ = require('lodash');
console.log( _.includes(switched, item[csvBusinessType]));
I converted the object to string and used includes, I don't know if it will be the best way, but I think it is the most supported by browsers
let businessListArray = JSON.stringify(switched);
let checkBusiness = businessListArray.includes(item[csvBusinessType]);
I want to validate if every item of the result contains words of switched
If you want to validate that every item of the result object array contains words of the switched array, you should look into JS Array methods and working with Objects, just as #Andreas suggested.
In this specific case, your switched object has keys that appear to match the csvBusinessType of your item objects. This is helpful as we can use Object.keys() to grab all the keys of your switched object as an array of strings.
const businessTypes = Object.keys(switched) // = ["Restaurant","Hotel","Beauty shop","Physiotherapist","Dentist","Bar","Coffee shop"]
Now that we have grabbed the keys that you want to check against, we can use the JS Array method every() to perform a test against every object in your result object array. In this case, we will be testing that the obect's Business Type is included in our newly created businessTypes array.
const resultsValid = result.every((resultObject) => businessTypes.includes(resultObject["Business Type"]));
resultsValid is a boolean that is true if all objects in result had a Business type that matched one of the keys of your switched object.
NOTE: You may want to check Letter Casing before some of these comparisons unless you want to explicitly match only exact matches ("Beauty shop" will NOT match "Beauty Shop" for example).
We have a nested dataLayer variable on our booking platform. Users can make one or multiple variables are we want to pull out a string containing each of the product types contained within the array. I am hitting a error when debugging this however.
The location of the variable I would like to collect is:
dataLayer.booking.products[i].travelType
try{
var productList = {};
for(i=0;i<dataLayer.booking.products.length;i++){
productList[dataLayer.booking.products[i].travelType];
}
return productList.join('|');
}
catch(err){}
I am naive with JS so I apologies for a basic question.
M
Your code shows that you're setting a new property of the object productList, but you're not defining a value, e.g. {foo: } instead of {foo: "bar"}. It looks like what you want is an array that you can add strings to. For example:
var productList = dataLayer.booking.products.map(function(product) {
return product.travelType;
});
return productList.join('|');
Note that this is using the Array's map method as opposed to your for loop. You could also define productList as an array in a previous line, and then use the forEach method on the products Array to loop through every item, but I think this is cleaner and still legible. You can reduce the code further with ES6 syntax, but for your question it's probably better to show code that is more clearly defined.
I've an array (example array below) -
a = [{"name":"age","value":31},
{"name":"height (inches)","value":62},
{"name":"location","value":"Boston, MA"},
{"name":"gender","value":"male"}];
I want to iterate through this array of objects and produce a new Object (not specifically reduce).
I've these two approaches -
a = [{"name":"age","value":31},
{"name":"height (inches)","value":62},
{"name":"location","value":"Boston, MA"},
{"name":"gender","value":"male"}];
// using Array.prototype.map()
b = a.map(function(item){
var res = {};
res[item.name] = item.value;
return res;
});
console.log(JSON.stringify(b));
var newObj = [];
// using Array.prototype.forEach()
a.forEach(function(d){
var obj = {};
obj[d.name] = d.value;
newObj.push(obj)
});
console.log(JSON.stringify(newObj))
Is it not right to just use either one for this sort of operations?
Also, I'd like to understand the use case scenarios where one will be preferred over the other? Or should I just stick to for-loop?
As you've already discussed in the comments, there's no outright wrong answer here. Aside from some rather fine points of performance, this is a style question. The problem you are solving can be solved with a for loop, .forEach(), .reduce(), or .map().
I list them in that order deliberately, because each one of them could be re-implemented using anything earlier in the list. You can use .reduce() to duplicate .map(), for instance, but not the reverse.
In your particular case, unless micro-optimizations are vital to your domain, I'd make the decision on the basis of readability and code-maintenance. On that basis, .map() does specifically and precisely what you're after; someone reading your code will see it and know you're consuming an array to produce another array. You could accomplish that with .forEach() or .reduce(), but because those are capable of being used for more things, someone has to take that extra moment to understand what you ARE using them for. .map() is the call that's most expressive of your intent.
(Yes, that means in essence prioritizing efficiency-of-understanding over efficiency-of-execution. If the code isn't part of a performance bottleneck in a high-demand application, I think that's appropriate.)
You asked about scenarios where another might be preferred. In this case, .map() works because you're outputting an array, and your output array has the same length as your input array. (Again; that's what .map() does). If you wanted to output an array, but you might need to produce two (or zero) elements of output for a single element of input, .map() would be out and I'd probably use .reduce(). (Chaining .filter().map() would also be a possibility for the 'skip some input elements' case, and would be pretty legible)
If you wanted to split the contents of the input array into multiple output arrays, you could do that with .reduce() (by encapsulating all of them as properties of a single object), but .forEach() or the for loop would look more natural to me.
First, either of those will work and with your example there's no reason not to use which ever is more comfortable for your development cycle. I would probably use map since that is what is for; to create "a new array with the results of calling a provided function on every element in this array."
However, are you asking which is the absolute fastest? Then neither of those; the fastest by 2.5-3x will be a simple for-loop (see http://jsperf.com/loop-vs-map-vs-foreach for a simple comparison):
var newObj = [];
for (var i = 0, item; item = a[i]; i++) {
var obj = {};
obj[item.name] = item.value;
newObj.push(obj);
});
console.log(JSON.stringify(newObj));
I have a scenario, where I have two different Objects.
Scenario to achieve:
From two objects I need to match the values which has "A1","B2", etc...
Since both the objects values are not in proper order, the loop is breaking and missing some values.
In my demo the object1 has same repeated value i.e. "C3", It should be displayed only once.
Final output required is I need to detect only the matched values from two objects and display its corresponding "a" and "b values."
I have tried almost 90%, but somewhere some minor error is breaking my loop, Please help me out.
Sample code:
for(var i=0;i<obj1.results[0].loc.length;i++){
var findA = obj1.results[0].loc[i].anc[0].title;
for(var j=0;j< obj2.ILoc.length;j++){
var findB = obj2.ILoc[j].ais;
if(findA == findB) {
var a = obj1.results[0].loc[i].a;
var b = obj1.results[0].loc[i].b;
console.log(a);
console.log(b);
}
}
}
This is what I have tried:
Demo Link
I would recommend using for...in loop, since you're using objects instead of arrays.
for (variable in object) {...
}
If length property of both objects is equal, then this kind of loop alone will help you to compare objects with ease.
I would recommend using the diff module. You can use it in node.js and the browser.
I have an ajax call that returns a JSON object that is pretty complex and I'm having a hard time sorting it.
My call:
$.post('/reports-ajax',arguments, function(data) {}
The response:
{
"10001":{
"unitname":"Fort Worth",
"discounts":{"12-02-2012":"34.810000","12-03-2012":"20.810000","12-04-2012":"27.040000"},
"gross":{"12-02-2012":"56.730000","12-03-2012":"19.350000","12-04-2012":"66.390000"},
"net":{"12-02-2012":"61.920000","12-03-2012":"98.540000","12-04-2012":"39.350000"},
"discounts_total":82.66,
"gross_total":82.47,
"net_total":99.81,
"number":10001
},
"10002":{
"unitname":"Dallast",
"discounts":{"12-02-2012":"12.600000","12-03-2012":"25.780000","12-04-2012":"47.780000","12-05-2012":"45.210000"},
"gross":{"12-02-2012":"29.370000","12-03-2012":"91.110000","12-04-2012":"60.890000","12-05-2012":"51.870000"},
"net":{"12-02-2012":"16.770000","12-03-2012":"65.330000","12-04-2012":"13.110000","12-05-2012":"06.660000"},
"discounts_total":131.37,
"gross_total":33.24,
"net_total":101.87,
"number":10002
},
"32402":{
"unitname":"Austin",
"discounts":{"12-05-2012":"52.890000","12-02-2012":"22.430000","12-03-2012":"58.420000","12-04-2012":"53.130000"},
"gross":{"12-05-2012":"25.020000","12-02-2012":"2836.010000","12-03-2012":"54.740000","12-04-2012":"45.330000"},
"net":{"12-04-2012":"92.200000","12-05-2012":"72.130000","12-02-2012":"13.580000","12-03-2012":"96.320000"},
"discounts_total":186.87,
"gross_total":161.1,
"net_total":174.23,
"number":32402
}
}
I go over the function with a standard each call and do some awesome stuff with highcharts but now I'm trying to sort the responses by the net_total call and I can't figure it out.
I tried .sort() and it errors out that its not a function. I've been reading for a while but guess I'm not finding the right results. This looked promising: Sorting an array of JavaScript objects but it failed with the .sort is not a function. It seems most .sort are on [] arrays not full objects..
Any help would be greatly appreciated.
Sorting objects doesn't make sense since object keys have no positional value. For example, this:
{ a:1, b:2 }
and this:
{ b:2, a:1 }
are exactly the same object. They're not just similar, they're the same.
Nothing in javascript per se gives object keys any positional value. Some people perhaps are mistaken in the belief that:
for (var key in obj) {
iterates through the object keys in a specific sequence. But this is wrong. You should always assume that the for .. in loop processes object keys in random order, always, all the time.
Obviously, if you're going to write a web browser, you're not going to implement a random number generator to parse a for .. in loop. Therefore most web browsers have an accidental stability to how the for .. in loop processes object keys.
Developers who learn javascript by playing around with the browser may figure out that their browser iterates through objects in alphabetical order for example, or the order the keys were added to the object. But this is totally accidental and cannot be relied upon. The browser vendor may change this behavior in the future without violating any backwards compatability (except with buggy scripts written by people who believe objects have a sort order). Not to mention that different browsers have different implementations of javascript and therefore not necessarily have the same internal key ordering of objects.
All the above is besides the point. "Key sort order" does not make any sense in javascript and any behavior observed is merely implementation detail. In short, javascript object does not have key order, just assume it's random.
Solution
Now, what you're really trying to do is not sort the object (you can't, it doesn't make sense). What you're really trying to do is process the object attributes in a specific order. The solution is to simply create an array (which has sorting order) of object keys and then process the object using that array:
// First create the array of keys/net_total so that we can sort it:
var sort_array = [];
for (var key in Response) {
sort_array.push({key:key,net_total:Response[key].net_total});
}
// Now sort it:
sort_array.sort(function(x,y){return x.net_total - y.net_total});
// Now process that object with it:
for (var i=0;i<sort_array.length;i++) {
var item = Response[sort_array[i].key];
// now do stuff with each item
}
What you have there isn't an array and has no order, so you'll have to transform it into an array so you can give it order.
Vaguely:
var array = [];
$.each(data, function(key, value) {
array.push(value);
});
array.sort(function(a, b) {
return a.net_total - b.net_total;
});
Live Example | Source
As GolezTroi points out in the comments, normally the above would lose the key that each entry is stored under in data and so you'd add it back in the first $.each loop above, but in this case the entries already have the key on them (as number), so there's no need.
Or you can replace the first $.each with $.map:
var array = $.map(data, function(entry) {
return entry;
});
// ...and then sort etc.
...whichever you prefer.