changing the values in an array using foreach Javascript - javascript

I am working on foreach in javascript, and I am wondering how to replace its old value to the new value in an array.
Let say I have this array
var myArray = [];
and then I have this variables to store the value
var name = [{name: "Peter"}, {name:"Jimmy"}, {name: Bob}];
var country = [{country: "Canada"}, {country:"Mexico"}, {country: "United States"}];
After I push the array, and display it to the views, I should have something like this in the table:
Name: Country:
Peter Canada
Jimmy Mexico
Bob United States
Then I also have the edit button so that I can edit the content in the table
Name: Country:
Peter Canada
Jimmy Mexico
Bob United States
<button ng-click="editDetail()">Edit Button </button>
What I want to do is, I want to change to be able to replace the old content to new content in the table and save it back to the array.
Name: Country:
Amy Britian
Jimmy Spain
Ken United States
How can I use foreach methods to do it? I am not sure what to do in this foreach function. Help will be appreciated :)
myArray.foreach(function(){
})

What you'll want to do is not use forEach, but use map, which essentially is the same, but you'll return a new array with your new data replacing the old data.
See the Mozilla Docs
var myNewArray = myArray.map(function(d) {
return d;
});

Related

Leaflet Maps: How to create an overlay with key/value pairs using the contents from an array?

In my project, when I load a page I pull a list of overlay names from the database, these are stored in a JS Array.
Using the default code below, how do I fill the overlayMaps with contents from an array rather than hard coding what the values will be:
var overlayMaps = {
"Cities": cities,
"Towns": towns
};
So as an example, instead of creating overlayMaps with the hard coded values Cities & Towns, I need to pull these values from an array that gets its data from the DB, The array in leymans terms might look like this under the hood:
[ "MyValue1": myvalue1,"MyValue2": myvalue2, "MyValue2": myvalue2,] etc
Maybe I need to create a dictionary, although I have no experience doing this in JS, only in C#
Am using guide: https://leafletjs.com/examples/layers-control/
Solution:
Reading the leaflet API instructions, you can actually add a single item to an L.control
one at a time using the command addOverlay( layer, name). Adds an overlay (checkbox entry) with the given name to the control. For demo purposes below, I'm using the same value var cities for each of the three checkboxes, but to show how we add the individual items from the array, we're looping through this array and adding the items one at a time.
var littleton = L.marker([39.61, -105.02]).bindPopup('This is Littleton, CO.'),
denver = L.marker([39.74, -104.99]).bindPopup('This is Denver, CO.'),
aurora = L.marker([39.73, -104.8]).bindPopup('This is Aurora, CO.'),
golden = L.marker([39.77, -105.23]).bindPopup('This is Golden, CO.');
var cities = L.layerGroup([littleton, denver, aurora, golden]);
var places = new Array()
places.push("Cities");
places.push("Towns");
places.push("MyPlaces");
var lControl = L.control.layers(null, null);
lControl.addTo(map);
places.forEach(myFunction);
function myFunction (item) {
lControl.addOverlay(cities, '' + item + '');
}

jQuery: Get total of same string from table [closed]

Closed. This question does not meet Stack Overflow guidelines. It is not currently accepting answers.
Questions asking for code must demonstrate a minimal understanding of the problem being solved. Include attempted solutions, why they didn't work, and the expected results. See also: Stack Overflow question checklist
Closed 9 years ago.
Improve this question
i got a table with td's that look like this:
Country | City | Number
Thailand | Phuket | 25
Thailand | Bangkok | 12
China | Wenzhou | 1
Australia | Sydney | 2
Vietnam | Saigon | 4
China | Beijing | 3
USA | New York | 4
USA | Miami | 2
How can i get a total for each country, ie Thailand = 37 (25+12), via jQuery (or plain JS)?
It would be simple if I could define each country however these values comes from a database and it can be over 50 countries/cities so need to put each in an array first and then somehow use inArray and add Number to already existing array if it exists.
Updated with jsfiddle: http://bit.ly/1iizLAt
JavaScript objects are essentially key/value maps, so you can track the total for the countries even though you don't know in advance what their names are:
To create the map:
var countryCounts = {};
I assume you can use the jQuery API to loop through the rows of the table, and get the country name for the row; let's say you put it in the variable country. Then, to count a time you've seen the country (in the loop):
countryCounts[country] = (countryCounts[country] || 0) + 1;
(Note that this assumes there's no chance that a country will have the name of any of the properties that exist by default on Object.prototype, such as toString or valueOf.)
That line looks a bit tricky, in two ways, so here's how it works:
You can look up a property name on an object either using dot notation and a property name literal, e.g., obj.foo, or by using bracketed notation and a string, e.g. obj["foo"]. In the latter case, the string can be the result of any expression. So if country is "Thailand", countryCounts[country] looks up the property Thailand on countryCounts.
If you look up a propery that doesn't exist on the object, you get back undefined, which is a "falsey" value. JavaScript's curiously-powerful || operator returns the first non-falsey (truthy) argument you give it. So countryCounts[country] || 0 will give you countryCounts[country] if that value is truthy, or 0 if countryCounts[country] is falsey. So you end up with the current count for the country, or the number 0. Then we add one to it and store it.
Then to loop through the results in countryCounts:
for (country in countryCounts) {
if (countryCounts.hasOwnPropery(country)) {
// Use `country` and `countryCounts[country]`
}
for-in loops through the names of the enumerable properties of an object. Using hasOwnProperty is a bit paranoid here, but it's good practice; it weeds out any enumerable properties that might exist on the object's prototype. (There are no enumerable properties on Object.prototype, and if you catch someone adding any you should give them a Severe Talking To, but still it's good practice.)
In the comments below, ajax333221 suggests "normalizing" the country name a bit just in case you have both Thailand and thailand (which would be separate properties in JavaScript, since JavaScript is case-sensitive). It's a good idea. At the very least, I would make the name all-lower-case, and his/her suggestion is to remove spaces as well, which is probably a good idea and unlikely to create confusion. If you want the names for display purposes, you could store the first one you see (without making it lower case and removing spaces) in a separate map:
realCountry = /*...get the real country name...*/;
country = country.toLowerCase().replace(/ /g, '_');
if (!mungedNameMap.hasOwnProperty(country)) {
mungedNameMap[country] = realCountry;
}
Then looking up the "munged" name in mungedNameMap will give you the first un-munged version you saw.
I'd first get the data in a format that you can play with in js:
var data = [
{country: 'Thailand', city: 'Asia', number: 25},
{country: 'Thailand', city: 'Bangkok', number: 12},
{country: 'China', city: 'Wenzhou', number: 1},
{country: 'Australia', city: 'Sydney', number: 2},
{country: 'Vietnam', city: 'Saigon', number: 4},
{country: 'China', city: 'Beijing', number: 3},
{country: 'USA', city: 'New', number: 4},
{country: 'USA', city: 'Miami', number: 2}
]
Once you have that, you can sum the number for matching countries:
var counts = {};
for (var i=0; i < data.length; i++){
var row = data[i];
counts[row.country] = (counts[row.country] || 0) + 1;
}
or, if you wanted a more functional approach, you could use Array.reduce
var counts = data.reduce(function(memo, row){
memo[row.country] = (memo[row.country] || 0) + 1;
return memo;
},{});

Grouping results in KO.js foreach binding

I can't figure out how to work with iterations in foreach of KOjs.
What I need is to group contents of an array like this
Var x = [{name: Joel, sex: male}, {name: Eric, sex: male},{name:Elliot, sex:female}, {name:Mary, sex:female}]
So the resulting data-bind foreach would display the sex of the person, but only once as a label.
Something like this
-male
Joel
Eric
-female
Elliot
Mary
With normal for loops it is as simple as making a variable that holds last entry's gender, and prints the new one if it changes. Something like
If(this.sex != cachedSex){
cachedSex=this.sex;
console.log(cachedSex);
}
But I can't figure it out how to make this in KO.js
Please give me an advice.
Knockout lets you use computed observables which solve this problem in a clever way :)
If you want a full code example here is a fiddle illustrating this solution.
Lets say all your people are called people and it's an observableArray :
var that = this;
this.people = ko.observableArray([{name: Joel, sex: male}, {name: Eric, sex: male},{name:Elliot, sex:female}, {name:Mary, sex:female}])
Now we only want the males and females apart:
this.males = ko.computed(function(){
return that.people().filter(function(person){
return person.sex === "male";
});
});
this.females = ko.computed(function(){
return that.people().filter(function(person){
return person.sex === "females ";
});
});
(Of course - if you repeat this sort of code a lot - make a function out of it instead of repeating yourself :) )
Then you can do the foreach binding normally, once for females and once for males
Benjamins answer is correct but there is another way without having to create additional observableArrays. In the view you can simply do a foreach binding and put a sliver of logic there to handle filtering. Its the simplest way but down the road you could argue there may be alternatives such as benjamins which are more suited, depending on your application
Men
This would allow you to do some basic filtering in the view. You could also set up a custom binding handler that you could pass in the filter to make it even more efficient and clean

getting correct type and format out of a jQuery.map() function

I hard coded the following array and I can use it to insert selections into an Autocomplete dropdown. It seems to be an array of JSON objects, though I am a JS novice and could be wrong. It works.
var boroughData = [
{"label":"New York, Bronx, Bronx County, New York, United States","value":"Bronx, Bronx County, New York, United States"},
{"label":"New York, Staten Island, Richmond County, New York, United States","value":"Staten Island, Richmond County, New York, United States"}
];
I want to provide similar data from a database and assemble it via a .map() function. I have something working, but the output is a different format/type. It seems to be an array with one long string, though again, I could be wrong. An example (with different cities) is below. Note the initial and ending " that is not in my hard coded array above.
["{"label":"Dallas, Cockr... Texas, United States"}", "{"label":"Dallas, Downt... Texas, United States"}", "{"label":"Dallas, East ... Texas, United States"}"]
The data from the database currently looks like the following, though it could be changed, if that helps.
{"label":"Dallas, Cockrell Hill, Dallas County, Texas, United States", "value":"Dallas, Cockrell Hill, Dallas County, Texas, United States"}
I tried string manipulation to replace/remove the initial and ending " but I could not get it to work. Maybe I need something different in the .map() function to create objects. My .map() in an ajax success option is as follows
success: function (data){
boroughData = $.map( data, function (item){
return item.boroughString;
//returning {"label":"Dallas, Cockrell Hill, Dallas County, Texas, United States", "value":"Dallas, Cockrell Hill, Dallas County, Texas, United States"}
});
alert(jQuery.isArray(boroughData) + "|bD1"); //true, is array
return boroughData;
}
How do I get a return result that is the same type/format as my hard coded array? Please be specific with code. I don't follow general instructions well.
Since the data that you get in item.boroughString is a string, you probably can parse it with JSON.parse (or use json2.js for browsers who don't support this functionality - see also this question : Parse JSON in JavaScript?) and it should convert you this string in a full JSON object.
$.ajax({
success: function (data){
boroughData = $.map( data, function (item){
return JSON.parse(item.boroughString);
// should return JSON object {"label":"Dallas, Cockrell Hill, Dallas County, Texas, United States", "value":"Dallas, Cockrell Hill, Dallas County, Texas, United States"}
});
alert(jQuery.isArray(boroughData) + "|bD1"); //true, it is again an array
//return boroughData; Your success should not return a variable to be used after!!! Ajax is asynchronous
//
// Rather use a callback function
functionToBeExecutedAfterTheSuccess();
}
});
function functionToBeExecutedAfterTheSuccess() {
alert(boroughData + "|bD3"); //[object Object],[object Object],[object Object] with OK contents
}
It seems to me that the best thing you can do is to make sure the server returns a valid JSON object. It is usually not recommended to fix something in Javascript that can be fixed server side.
That said, the way to transform the string into the array that is equal to the hard coded array, you can use this:
success: function (data){
// split the data with separator ",
var parts = data.split("\",");
var boroughData = [];
// looping through all parts
for (var i=0, ii=parts.length; i < ii; i++) {
// getting the value of the part between { and }
var part = parts[i].substring(parts[i].indexOf("{"),parts[i].indexOf("}")+1);
// add part as json to the array
boroughData.push($.parseJSON(part));
}
return boroughData;
}

Autocomplete problem with two identical "values"

I'm using the JQuery Autocomplete plugin, with local data stored in a array:
data = [city1, city2, city3, city1]
Once the user selects the data element, for example city 1, I store it in user_input. I use the user input to read a hash that contains city, state zip, and name. The script displays each element of the hash on screen when the user hits enter. This also works great:
$(document).keypress(function(e) {
if(e.keyCode == 13) {
var user_input = $("input#example").val()
$.each(personinfo,function(key,value){
if(value['city']== user_input){
$('#city').empty().append(value['city']);
$('#state').empty().append(value['state']);
$('#zip').empty().append(value['zip']);
$('#name').empty().append(value['name']);
}
})
The problem arises when there are two identical keys. For instance, say a name "John Doe" and "Jane Doe", live in the same city: city1. Therefore city1 appears twice in the data array, as you see above.
data is defined in this method:
var data = new Array();
$(document).ready(function(){
$.each(personinfo,function(key,value){
myarray.push(value['city'])
});
});
How can I differentiate amongst city1 and city1 in the above array within the keypress function?
The personinfo map object:
{"address":"07288 Albertha Station","city":"Littelside","created_at":"2011-05-25T19:24:51Z","id":1,"name":"Jane Doe","state":"Missouri","updated_at":"2011-05-26T21:25:54Z","zip":"75475-9938"},{OBJECT 2}, {OBJECT 3}, ....
As some of the comments suggest, it's impossible to fix a problem with identical keys: the only way to fix it is to use non-identical keys :-)
I'd just combine city and state to make the key; seems like that should give you a unique keyset.
It's probably late now, but I just had to fix this problem in a similar plugin and the best way of doing it is to pass additional reference with the lookup data.
As in lookup = { data: ['name1', 'name2', 'name2', 'namex'], ref:[1,2,3,4] }
So that when user selects second 'name2' the plugin will return selected 'name2' and ref 3.
It depends on a plugin if it supports this functionality, but even if it doesn't you should be able to modify it slighlty.

Categories