I wonder how I can separate an array that consists of "123.152323,152.123232" into "123.152323" and "152.123232".
I pick up the string from a rest, the string looks like this.
responseHandler({"items":[{"name":"xxx","location":["xx.xxxxx","xx.xxxxx"]...
function responseHandler(json) {
var markers = new Array();
for (var i = 0; i < json.items.length; i++) {
markers[i] = (json.items[i].location);
}
}
Can I split the location before putting it into an array? I know split() exists but if the string has more information than just location, such as name, city, etc.
Why reinvent the wheel ? It seems like you have a valid json object, Why not simply use JQuery.parseJSON
Modern browser contain native JSON methods (like JSON.parse, JSON.stringify). Use those, or use an external library like this one from google. It makes your life easier (no need for splitting or regex searches and the like):
function responseHandler(json) {
// use native (JSON.parse), json-sans-eval would be: jsonParse(json)
var myJson = JSON.parse(json)
,markers = []
,i = 0
,len = myJson.length;
for (; i < len; i = i+1) {
markers.push(myJson[i].location);
}
return markers;
}
Edit after comment: you are passing a js-object, so JSON-parsing is not necessary.
function responseHandler(json) {
var markers = []
,i = 0
,len = json.length;
for (; i < len; i = i+1) {
markers.push(json.items[i].location);
}
return markers;
}
//for example
var json = {"items":[
{"name":"xxx","location":["xx.xxxxx","xx.xxxxx"]},
{"name":"yyy","location":["yy.yyyyy","yy.yyyyy"]}
]
};
var locations = responseHandler(json);
//=> now locations[0][0] is 'xx.xxxxx', locations[1][0] 'yy.yyyyy'
(May be you should try finding some reading material on the web about javascript basics)
Related
I have an array like this with names and address:
BTDevices = [
{name:"n1", address:"add1"},
{name:"n2", address:"add2"},
{name:"n3", address:"add3"}]
And another array with alias and address:
EqAlias = [
{btAlias:"a1", address:"add0"},
{btAlias:"a2", address:"add2"},
{btAlias:"a3", address:"add9"}]
I want to add btAlias property to all objects in BTDevices and set the value only if the address are the same, for example in this case I want the following result:
BTDevices:
name:"n1", address:"add1", btAlias:""
name:"n2", address:"add2", btAlias:"a2"
name:"n3", address:"add3", btAlias:""
My first solution was adding btAlias property using forEach and then using two for loops:
// Add Alias
this.BTDevices.forEach(function(obj) { obj.btAlias = "" });
// Set Alias
for (let m = 0; m < this.EqAlias.length; m ++)
{
for (let n = 0; n < this.BTDevices.length; n++)
{
if (this.BTDevices[n].address == this.EqAlias[m].address)
this.BTDevices[n].btAlias = this.EqAlias[m].btAlias;
}
}
Is there a better way to do the same? I guess using forEach
Using forEach instead of for will just replace the two for loop with forEach. We could argue on which is the best between for and forEach but i don't think there's a good answer. In modern javascript you can also use the for of loop.
Your algorithm is the simpliest and it will work.
But, if you want to address some performances issues, you should want to know that your algorithm is also the slowest (O(n²) complexity)
Another way to do that is to store items of BTDevices in a map to find them faster. Example:
let map = new Map();
BTDevices.forEach(e => map.set(e.address, e));
EqAlias.forEach(e => {
let device = map.get(e.address);
if (device) {
device.btAlias = e.btAlias;
}
});
The only advantage of this code is that looking for an item in a Map is faster (between O(1) and O(n), it depends of Map implementation). But you won't see any differences unless you try to manipulate some very big arrays.
You can use map and find
Use map to loop the array and create a new array.
Use find to check if a string is in an array.
let BTDevices = [{name:"n1", address:"add1"},{name:"n2", address:"add2"},{name:"n3", address:"add3"}];
let EqAlias = [{btAlias:"a1", address:"add0"},{btAlias:"a2", address:"add2"},{btAlias:"a3", address:"add9"}];
let result = BTDevices.map( v => {
v.btAlias = ( EqAlias.find( e => e.address == v.address ) || { btAlias:"" } ).btAlias;
return v;
});
console.log( result );
Please check doc: .map, .find
You could also do something like this.
var BTDevices = [{name:"n1", address:"add1"},{name:"n2", address:"add2"},{name:"n3", address:"add3"}];
var EqAlias = [{btAlias:"a1", address:"add0"},{btAlias:"a2", address:"add2"},{btAlias:"a3", address:"add9"}];
var EqAliasAdd = EqAlias.map((e)=>e.address);
var BTDevicesAdd = BTDevices.map((e)=>e.address);
BTDevicesAdd.map(function(i,k) {
BTDevices[k].btAlias = "";
if(EqAliasAdd.indexOf(i) >= 0)
BTDevices[k].btAlias = EqAlias[k].btAlias;
});
console.log(BTDevices);
I'm going crazy for i do not understand the behavior of my loop!
here a sample of a json I read :
[{"type":"robot","town":"NANTES","region":"Ouest","performances":[{"date":YYYY-MM-DD","value":100},{...}],"availability":[{"date":"YYY-MM-DD","value":100},{...}]},{"type":"robot","town":"RENNES","region":"Ouest","performances":[{"date":YYYY-MM-DD","value":100},{...}],"availability":[{"date":"YYY-MM-DD","value":100},{...}]}
I create 2 objects :
REGIONS = {},TOWNS= {};
here is the function the moment i recieve the object:
function getRobotsDatas(robotList) {
for (var i = 0; i < robotList.length; i++) {
var robot = robotList[i];
// working on TOWNS object
//I check if the "town" object of TOWNS object already exist
if (TOWNS[robot.town] === undefined) {
// if not, i create it
TOWNS[robot.town] = {};
//then i push performances datas of my robot in my TOWNS.town object
TOWNS[robot.town].performances = robot.performances;
// the same for availability datas
TOWNS[robot.town].availability= robot.availability;
}
// then I work nearly the same way on REGIONS object.
//i check if the "region" object exist in REGIONS object. If not, i create it and add the perf+availability datas of the robot.
if (REGIONS[robot.region] === undefined) {
REGIONS[robot.region] = {};
REGIONS[robot.region].performances = robot.performances;
REGIONS[robot.region].availability= robot.availability;
}
// If the REGIONS.region already exist, i just want to add the datas of performances and availability in the already existing arrays of REGIONS.region (performances[] and availabilities[])
else {
for (var j = 0; j < robot.performances.length; j++) {
REGIONS[robot.region].performances.push(robot.performances[j]);
}
for (var k = 0; k < robot.availability.length; k++) {
REGIONS[robot.region].availability.push(robot.availability[k]);
}
}
}
The problem is that the condition for an already existing "REGIONS.region" is also applied on TOWNS. It adds values of performances and availabilities in the TOWNS objects of the robots which have the same value of the "region" attribut.
for example, in the sample i gave at the beginning, i'll find availabilities and perf datas in a new object : REGIONS.Ouest {performances:[...], availability:[...]}, but i will also find NANTES' perf an availibilities datas in RENNES' perf and availabilities arrays... and THAT, i don't want!
What's wrong with my condition / loop!???
Your code refers to 'town' but your incoming JSON has 'ville' instead.
I appreciate that this won't fix the problem, but the example should at least be correct.
The incoming JSON has two sub-objects. For each one, you test for presence in your Towns and Regions data structures. If they don't each have a matching entry, you are creating one, and then adding entries in the two further sub-objects (performances and availability).
If you don't want this in both cases, you need to test the incoming JSON appropriately.
This is a problem of variable Reference. try this simple change JSON.parse(JSON.stringify(xxx))
function getRobotsDatas(robotList) {
for (var i = 0; i < robotList.length; i++) {
var robot = robotList[i];
if (TOWNS[robot.town] === undefined) {
TOWNS[robot.town] = {};
TOWNS[robot.town].performances = JSON.parse(JSON.stringify(robot.performances));
TOWNS[robot.town].disponibilite = JSON.parse(JSON.stringify(robot.availability));
}
if (REGIONS[robot.region] === undefined) {
REGIONS[robot.region] = {};
REGIONS[robot.region].performances = robot.performances;
REGIONS[robot.region].availability= robot.availability;
}
else {
for (var j = 0; j < robot.performances.length; j++) {
REGIONS[robot.region].performances.push(robot.performances[j]);
}
for (var k = 0; k < robot.availability.length; k++) {
REGIONS[robot.region].availability.push(robot.availability[k]);
}
}
}
}
JS is funny.... :)
I have the following array and a loop fetching the keys (https://jsfiddle.net/ytm04L53/)
var i;
var feeds = ["test_user_201508_20150826080829.txt:12345","test_user_list20150826:666","test_list_Summary20150826.txt:321"];
for (i = 0; i < feeds.length; i++) {
var feed = feeds[i];
alert(feed.match(/\d+$/));
}
The array will always contain different number of keys, What I would like to do is either use these keys as variables and assign the value after the : semicolon as its value or just create a new set of variables and assign the values found on these keys to them.
How can I achieve this? so that I can then perform some sort of comparison
if (test_user > 5000) {dosomething}
update
Thanks for the answers, how can I also create a set of variables and assign the array values to them? For instance something like the following.
valCount(feeds.split(","));
function valCount(t) {
if(t[0].match(/test_user_.*/))
var testUser = t[0].match(/\d+$/);
}
Obviously there is the possibility that sometimes there will only be 1 key in the array and some times 2 or 3, so t[0] won't always be test_user_
I need to somehow pass the array to a function and perform some sort of matching, if array key starts with test_user_ then grab the value and assign it to a define variable.
Thanks guys for all your help!
You can't (reasonably) create variables with dynamic names at runtime. (It is technically possible.)
Instead, you can create object properties:
var feeds = ["test_user_201508_20150826080829.txt:12345","test_user_list20150826:666","test_list_Summary20150826.txt:321"];
var obj = {};
feeds.forEach(function(entry) {
var parts = entry.split(":"); // Splits the string on the :
obj[parts[0]] = parts[1]; // Creates the property
});
Now, obj["test_user_201508_20150826080829.txt"] has the value "12345".
Live Example:
var feeds = ["test_user_201508_20150826080829.txt:12345","test_user_list20150826:666","test_list_Summary20150826.txt:321"];
var obj = {};
feeds.forEach(function(entry) {
var parts = entry.split(":");
obj[parts[0]] = parts[1];
});
snippet.log(obj["test_user_201508_20150826080829.txt"]);
<!-- Script provides the `snippet` object, see http://meta.stackexchange.com/a/242144/134069 -->
<script src="http://tjcrowder.github.io/simple-snippets-console/snippet.js"></script>
You can do it like this, using the split function:
var i;
var feeds = ["test_user_201508_20150826080829.txt:12345","test_user_list20150826:666","test_list_Summary20150826.txt:321"];
for (i = 0; i < feeds.length; i++) {
var feed = feeds[i];
console.log(feed.split(/[:]/));
}
This outputs:
["test_user_201508_20150826080829.txt", "12345"]
["test_user_list20150826", "666"]
["test_list_Summary20150826.txt", "321"]
Use the split method
var feeds = ["test_user_201508_20150826080829.txt:12345","test_user_list20150826:666","test_list_Summary20150826.txt:321"];
feedMap = {}
for (i = 0; i < feeds.length; i++) {
var temp = feeds[i].split(':');
feedMap[temp[0]] = temp[1];
}
Yields:
{
"test_user_201508_20150826080829.txt":"12345",
"test_user_list20150826":"666",
"test_list_Summary20150826.txt":"321"
}
And can be accessed like:
feedMap["test_user_201508_20150826080829.txt"]
Here is a codepen
it is not very good idea but if you really need to create variables on-the-run here's the code:
for (i = 0; i < feeds.length; i++)
{
var feed = feeds[i];
window[feed.substring(0, feed.indexOf(":"))] = feed.match(/\d+$/);
}
alert(test_user_201508_20150826080829)
Of course you cannot have any variable-name-string containing banned signs (like '.')
Regards,
Michał
I've been losing hours over something that might be trivial:
I've got a list of comma-separated e-mail addresses that I want to convert to a specific JSON format, for use with the Mandrill API (https://mandrillapp.com/api/docs/messages.JSON.html)
My string:
var to = 'bigbadwolf#grannysplace.com,hungry#hippos.com,youtalkin#to.me';
What (I think) it needs to be:
[
{"email": "bigbadwolf#grannysplace.com"},
{"email": "hungry#hippos.com"},
{"email": "youtalkin#to.me"}
]
I've got a JSFiddle in which I almost have it I think:
http://jsfiddle.net/5j8Z7/1/
I've been looking into several jQuery plugins, amongst which: http://code.google.com/p/jquery-json
But I keep getting syntax errors.
Another post on SO suggested doing it by hand: JavaScript associative array to JSON
This might be a trivial question, but the Codecadamy documentation of the Mandrill API has been down for some time and there are no decent examples available.
var json = [];
var to = 'bigbadwolf#grannysplace.com,hungry#hippos.com,youtalkin#to.me';
var toSplit = to.split(",");
for (var i = 0; i < toSplit.length; i++) {
json.push({"email":toSplit[i]});
}
Try this ES6 Version which has better perform code snippet.
'use strict';
let to = 'bigbadwolf#grannysplace.com,hungry#hippos.com,youtalkin#to.me';
let emailList = to.split(',').map(values => {
return {
email: values.trim(),
}
});
console.log(emailList);
Try changing the loop to this:
var JSON = [];
$(pieces).each(function(index) {
JSON.push({'email': pieces[index]});
});
How about:
var to = 'bigbadwolf#grannysplace.com,hungry#hippos.com,youtalkin#to.me',
obj = [],
parts = to.split(",");
for (var i = 0; i < parts.length; i++) {
obj.push({email:parts[i]});
}
//Logging
for (var i = 0; i < obj.length; i++) {
console.log(obj[i]);
}
Output:
Object {email: "bigbadwolf#grannysplace.com"}
Object {email: "hungry#hippos.com"}
Object {email: "youtalkin#to.me"}
Demo: http://jsfiddle.net/tymeJV/yKPDc/1/
Hi
I have a javascript array object rapresenting the amount of items sold in a given country, like this:
var data = [{'c1':'USA', 'c2':'Item1', 'c3':100},
{'c1':'Canada', 'c2':'Item1', 'c3':120},
{'c1':'Italy', 'c2':'Item2', 'c3':140},
{'c1':'Italy', 'c2':'Item2', 'c3':110}]
I need to avoid duplicates (as you may see, the last two 'records' have the same Country and the same Item) and sum the amounts; if I was getting data from a database I would use the DISTINCT SUM clause, but what about it in this scenario? Is there any good jquery trick?
You could use an object as a map of distinct values, like this:
var distincts, index, sum, entry, key;
distincts = {};
sum = 0;
for (index = 0; index < data.length; ++index) {
entry = data[index];
key = entry.c1 + "--sep--" + entry.c2;
if (!distincts[key]) {
distincts[key] = true;
sum += entry.c3;
}
}
How that works: JavaScript objects are maps, and since access to properties is an extremely common operation, a decent JavaScript implementation tries to make property access quite fast (by using hashing on property keys, that sort of thing). You can access object properties using a string for their name, by using brackets ([]), so obj.foo and obj["foo"] both refer to the foo property of obj.
And so:
We start with an object with no properties.
As we loop through the array, we create unique key from c1 and c2. It's important that the "--sep--" string be something that cannot appear in c1 or c2. If case isn't significant, you might throw a .toLowerCase in there.
If distincts already has a value for that key, we know we've seen it before and we can ignore it; otherwise, we add a value (true in this case, but it can be just about anything other than false, undefined, 0, or "") as a flag indicating we've seen this unique combination before. And we add c3 to the sum.
But as someone pointed out, your last two entries aren't actually the same; I'm guessing that was just a typo in the question...
jQuery may have an array function for this, but because your two Italy objects are not distinctly unique, your asking for a custom solution. You want to populate a array and check it for duplicates as you go:
var data = [{'c1':'USA', 'c2':'Item1', 'c3':100},
{'c1':'Canada', 'c2':'Item1', 'c3':120},
{'c1':'Italy', 'c2':'Item2', 'c3':140},
{'c1':'Italy', 'c2':'Item1', 'c3':110}]
var newArray = [];
var dupeCheck = {}; // hash map
for(var i=0; i < data.length; i++){
if(!dupeCheck[data[i].c1]){
newArray.push(data[i]);
dupeCheck[data[i].c1] = true;
}
}
test
HTML:
<div id="test"></div>
JS:
var data = [{'c1':'USA', 'c2':'Item1', 'c3':100},
{'c1':'Canada', 'c2':'Item1', 'c3':120},
{'c1':'Italy', 'c2':'Item2', 'c3':140},
{'c1':'Italy', 'c2':'Item1', 'c3':110}];
var
l = data.length, // length
f = "", // find
ix = "", // index
d = []; // delete
for (var i = 0; i < l; i++) {
ix = data[i].c1 + "_" + data[i].c2 + "__";
//var re = new RegExp(ix);
//if (re.test(f))
if (f.indexOf(ix) != -1)
d.push(i);
else
f += ix;
}
for (var i1 = 0; i1 < d.length; i1++){
$("#test").append("<div>for delete: "+d[i1]+"</div>");
}
EDIT
Although chrome works much faster, works only in chrome faster the example with indexOf, then in IE/Opera/Firefox/Safary works faster with an object.
The code created by "# TJ Crowder" is much more efficient.