looping through collection of javascript objects - javascript

Am trying to read only very first element of friends array and add it to matches array for each object. If I add matches property directly on object. Then it returns expected result. But if I use a function addmatches to add matches array property. Then matches array value is coming same for each animal object.
var AnimalCreator = function(username, species, tagline, noises) {
var friends = [];
//var matches = [];
return {
username: username,
species: species,
tagline: tagline,
noises: noises,
friends: friends,
//matches: matches
}
};
var sheep = AnimalCreator('Cloud', 'sheep', 'You can count on me!', ['baahhh', 'arrgg', 'chewchewchew']);
var rabbit = AnimalCreator('Sky', 'Rabbit', 'I like jumping!', ['haha', 'heehee']);
var tiger = AnimalCreator('Tim', 'Tiger', 'I am strong!', ['Grrrr', 'grrrrrr!']);
var bear = AnimalCreator('Poo', 'Bear', 'I am your friend', ['wowo', 'whwhwh']);
var addFriend = function(animal, friend) {
animal.friends.push(friend.username);
};
addFriend(sheep, rabbit);
addFriend(sheep, tiger);
addFriend(tiger, bear);
var myFarm = [sheep, rabbit, tiger, bear];
var addmatches = function(farm){
var matches = [];
for(var i=0;i < farm.length; i++){
farm[i].matches = matches;
}
};
addmatches(myFarm);
var giveMatches = function(farm) {
for (var i = 0; i < farm.length; i++) {
if (farm[i].friends.length > 0) {
farm[i].matches.push(farm[i].friends[0]);
}
}
};
giveMatches(myFarm);
console.log(myFarm);

matches is a reference to an empty array and your code is assigning same reference for every farm object ( farm[i].matches = matches; ), you can try by assigning empty array directly like
farm[i].matches = [];
Your commented code: The function AnimalCreator is creating a new array instance on every call and every animal object is referencing to a unique array, that's why when you directly add matches, it works as expected.
Hope this will help!

This is because array is passed by referance, so every farm object is pointing to the same array by this "farm[i].matches = matches;". To fix this you can do multiple tihings.
Change "farm[i].matches = matches;" to "farm[i].matches = [];" (Best option as of now).
Move "var matches = [];" inside for loop and use "let" insted of "var".

Related

Push/update array from JavaScript to HTML

I have made a array of data from Firebase, and want to display it on my website. It works fine one time, but when Firebase is updated, the website doesn´t update correspondingly.
My goal is to make a list of updates. So when the database is updated, the new update is shown above the previous.
console.log(arr); logs every change made in the database, so basically I want what the console displays..
JS code:
firebase.initializeApp(config);
database = firebase.database();
var ref = database.ref("users");
ref.on("value", gotData, errData);
function gotData(data) {
// console.log(data.val);
var users = data.val();
var keys = Object.keys(users);
//console.log(keys);
for (var i = 0; i < keys.length; i++) {
var k = keys [i];
var name = users [k].Name;
var gender = users [k].Gender;
var car = users [k].Car;
var location = users [k].Location;
var destination = users [k].Destination;
// initialize array
var arr = [
name,
gender,
car,
location,
destination,
];
// append new value to the array
arr.push(destination);
document.getElementById('B1').innerHTML = JSON.stringify(arr);
console.log(arr);
}
}
function errData(err) {
console.log("Error");
console.log(err);
}
<!DOCTYPE html
<html>
<head
<meta charset="utf-8">
<title>Test</title>
<script src="https://www.gstatic.com/firebasejs/live/3.1/firebase.js"></script>
</head>
<body>
Test
<!-- Value -->
<ol id="B1"></ol>
<script src ="App.js"></script>
</body>
</html>
Firebasestructure:
App
users
09IEbFijEnQpDita5DyhUdBE0eD3
Name: "Nick"
Car: "Audi"
Gender: " Male"
Location: "Home"
Destination: " Beach"
Is there a good (and hopefully not to complicated) way to reach my goal?
Thank you.
You are resetting your array in every iteration, while you really want to keep the data from the previous iterations in there. So intitialise your array before entering the loop, and only add to it within the loop. In the same way you overwrite the output in the HTML element in each iteration. Instead, accumulate the data in the loop and only output the array after the loop:
function gotData(data) {
var users = data.val();
var keys = Object.keys(users);
// initialize array here
var arr = [];
for (var i = 0; i < keys.length; i++) {
var k = keys[i];
var name = users[k].Name;
var gender = users[k].Gender;
var car = users[k].Car;
var location = users[k].Location;
var destination = users[k].Destination;
// append new value to the array
arr.push([
name,
gender,
car,
location,
destination,
]);
}
// And now output:
document.getElementById('B1').innerHTML = JSON.stringify(arr);
console.log(arr);
}
All this can be done a bit shorter with the use of Object.values (assuming you want all the data fields):
function gotData(data) {
var arr = Object.values(data.val()).map(Object.values);
document.getElementById('B1').innerHTML = JSON.stringify(arr);
console.log(arr);
}
If you want the last value at the top of the output then use the reverse method, and if you want it in a list format then map the values to li tags. Finally, you may want to limit the number of rows to some constant (e.g. 10), which you can do with slice:
function gotData(data) {
var arr = Object.values(data.val()).map(Object.values);
B1.innerHTML = arr.slice(-10).reverse().map(val => `<li>${val}</li>`).join('');
}
Note that you don't really need document.getElementById nowadays, since browsers declare global variables for each of the elements with an id attribute. So you can just use the B1 variable.

Naming objects inside of an array dynamically

I'm quite new to JavaScript and programming in general and figured I'd hone my abilities by working on a small project. The idea is that I have a form for information on an event, an input for the name, date, time and a small thumbnail image.
I want each event to be an object inside of an array, so I would have something like:
var concerts = {};
for (var i = 1; i < 11; i++) {
window["concert"+i] = new Object();
}
and the array would end up being something:
var concerts = [concert1, concert2, concert3]
and so on.
How could I get this loop to work so that it would take the 3 parameters and create a new object in the array named 'concert'+i? Thanks for reading!
Concerts must be an array:
var concerts = [];
for (var i = 0; i < 10; i++) {
concerts[i] = {
//maybe also giveit a name if you want to:
name:"concert"+i
};
}
You can access it like this:
concerts[0].name="Wacken";//first concert...
Note that this:
window["concert"+i] = new Object();
is very bad style...
First you declare a variable concerts of type object. But you want an array. That first line makes your code very confusing.
You have to start with an empty array:
var concerts = []; // alternatively: new Array();
In the end you'd like to have a structure like this:
[
{ /* object 1 */ },
{ /* object 2 */ }
]
Now you can run a foor-loop and populate the array:
for (var i = 0; i <= 10; i++) {
concerts.push({['concert' + i]: {}});
}
This will return something like:
[
{'concert0': {}},
{'concert1': {}},
// skipped
{'concert10': {}}
]
Later you can populate the objects. This is however not a very nice style. Maybe you should reconsider if it is really necessary to give a name to every object like concert0...10.
Go rather for:
var concerts = [
{
'name': 'concert0',
'location': 'somewhere'
}
// continue with other objects
];

Create variables based on array

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ł

How to check an input words against several arrays in Javascript

I need to test all the words entered into an input against 3 objects and determine which array they belong to so I can output a URL to an API.
I want to achieve this with Javascript/jQuery.
For example if the input had these words: keyword1 keyword2 keyword3 keyword5
All keyword entries will be added from a autocomplete plugin.
I then need to test them against 3 arrays.
var array1 = ["keyword2", "keyword6"];
var array2 = ["keyword3", "keyword4"];
var array3 = ["keyword1", "keyword5"];
I need to determine what array they came from so I can output a URL and add the values to specific keys in a URL.
Example:
domain.com/api?array1= [insert keyword(s)] &array2= [insert keyword(s)] &array3= [insert keyword(s)]
The keywords need to be sent as an array and must have spaces replaced with dashes.
I am using jQuery to perform a GET request with the URL generated.
You can make the code shorter by creating an array of arrays but this works
var input = "keyword1 keyword2 keyword3 keyword5".split(" ");
var array1 = ["keyword2", "keyword6"];
var array2 = ["keyword3", "keyword4"];
var array3 = ["keyword1", "keyword5"];
var arr1=[],arr2=[],arr3=[];
$.each(input,function(_,keyword) {
if ($.inArray(keyword,array1) !=-1) arr1.push(keyword);
if ($.inArray(keyword,array2) !=-1) arr2.push(keyword);
if ($.inArray(keyword,array3) !=-1) arr3.push(keyword);
});
var url = "domain.com/api/?",keywords="";
if (arr1.length>0) keywords += "&array1="+arr1.join(",");
if (arr2.length>0) keywords += "&array2="+arr2.join(",");
if (arr3.length>0) keywords += "&array3="+arr3.join(",");
if (keywords.length>0) url += keywords.substring(1).replace(/ /g,"-");
console.log(url)
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
You can put all the array objects into a parent array and then loop it
var parentArray = [
["keyword2", "keyword6"],
["keyword3", "keyword4"],
["keyword1", "keyword5"]
]
$.each(parentArray,function(key,value){
//here you can check
$.each(value,function(key1,value1){
if('your key word') == value1{
// then the array you are looking for would be "key" of that particular loop
}
});
});
EDIT: Now, this should definitely work
Here's a vanilla JS version:
var words = 'keyword1 keyword2 keyword3 keyword5';
// first create an object that contains your arrays
var dict = {
array1: ["keyword2", "keyword6"],
array2: ["keyword3", "keyword4"],
array3: ["keyword1", "keyword5"]
}
// start building up a new object that mirrors the existing one
// but that only contains those keywords that are in the input string
function buildURLObj(dict, words) {
var out = {};
// split the keywords string into an array
words = words.split(' ');
// loop over the object
for (var p in dict) {
out[p] = [];
// loop over the array of keywords
for (var i = 0, l = words.length; i < l; i++) {
// if the keyword in the array, push it to the
// temporary object
if (dict[p].indexOf(words[i]) > -1) {
out[p].push(words[i]);
}
}
}
// return the completed URL using createURL
return createURL(out);
}
// create a URL from the new object
function createURL(arr) {
var url = [];
for (var p in arr) {
// if the array is not empty, don't add it to the completed URL
// otherwise start building up the URL string
if [arr[p].length) {
var subURL = [];
subURL.push(p);
subURL.push('[' + arr[p].join('-') + ']');
url.push(subURL.join('='));
}
}
// return the completed URL
return url.join('&');
}
// "array1=[keyword2]&array2=[keyword3]&array3=[keyword1-keyword5]"
buildURL(dict, words);
DEMO

create array, use $.each to loop, and add value if not in array

I have a bunch of .defined in a text and want to create an array of unique values with javascript. So basically, for each anchor with class defined, I want to first check the array to see if the pair already exists. If exists, go to next anchor. If does not exist, add to array. This is the code I have tried using, but it does not remove duplicate values.
var arr = new Array();
y = 0;
$("a.defined").each(function() {
var spanishWord = this.text;
var englishWord = this.title;
if(spanishWord in arr) {
console.log("do nothing");
} else {
arr.push({key: spanishWord, value: englishWord});
y++;
}
For example, I have these tags in the text:
<a title="read">Leer</a>
<a title="work">Trabajar</a>
<a title="like">Gustar</a>
<a title="read">Leer</a>
<a title="sing">Cantar</a>
<a title="like">Gustar</a>
And I would like my array to look like:
Spanish Word | English Word
Leer read
Trabajar work
Gustar like
Cantar sing
but instead it looks like:
Spanish Word | English Word
Leer read
Trabajar work
Gustar like
Leer read
Cantar sing
Gustar like
Any ideas?
I would do this in two steps.. one to eliminate duplicates, and one to create the array:
http://jsfiddle.net/uN4js/
var obj = {};
$('a.defined').each(function() {
obj[this.text] = this.title;
});
var arr = [];
for (var prop in obj) {
if (obj.hasOwnProperty(prop))
arr.push({key: prop, value: obj[prop]});
};
console.log(arr);
If the object is sufficient and you don't really need an array, you could stop after the object is created.
You can probably just use a javascript object here:
var dict = {};
y = 0;
$("a.defined").each(function() {
var spanishWord = this.text;
var englishWord = this.title;
dict[spanishWord] = englishWord;
}
And there isn't really a need for unique checks, since newer values will just overwrite the older ones. If you don't want that behaviour, you can do this:
var dict = {};
y = 0;
$("a.defined").each(function() {
var spanishWord = this.text;
var englishWord = this.title;
if (!(spanishWOrd in dict)) {
dict[spanishWord] = englishWord;
}
}
Javascript's in operator is not used for testing inclusion, it's used for iteration in a for .. in .. loop.
Other answers have suggested correctly that you need either .indexOf or JQuery's $.inArray method to test inclusion in an array, but there is a simpler (and faster) way of solving this problem: use a dictionary of key/value pairs instead!
var dict = {};
$("a.defined").each(function() {
dict[this.textContent] = this.title;
});
Afterwards, you can use for key in dict to iterate over the list of unique Spanish words, and dict[key] to get the corresponding English translation.
Try this:
JavaScript
var arr = {};
$("a").each(function() {
var spanishWord = this.text;
var englishWord = this.title;
if(spanishWord in arr) {
console.log("do nothing");
} else {
arr[spanishWord] = englishWord;
}
});
console.log(arr);

Categories

Resources