Push different object in an array with a for loop - javascript

I have an element structured like this:
Element ->
[{values: arrayOfObject, key:'name1'}, ... ,{values: arrayOfObjectN, key:'nameN'}]
arrayDiObject -> [Object1, Object2, ... , ObjectN] //N = number of lines in my CSV
Object1 -> {x,y}
I have to take data from a big string:
cityX#substanceX#cityY#substanceY#
I thought to make it this way, but it seems like it pushes always in the same array of objects. If I put oggetto = {values: arrayDateValue, key: key}; inside the d3.csv function, instead if I put outside the function it add me only empty objects.
Here is my code:
var final = new Array();
var oggetto;
var key;
function creaDati() {
var newdate;
var arrayDateValue = new Array();
var selString = aggiungiElemento().split("#");
//selString is an array with selString[0]: city, selString[1]: substance and so on..
var citySelected = "";
var substanceSelected = "";
for (var i = 0; i < selString.length - 1; i++) {
if (i % 2 === 0) {
citySelected = selString[i];
} else if (i % 2 !== 0) {
substanceSelected = selString[i];
key = citySelected + "#" + substanceSelected;
d3.csv("/CSV/" + citySelected + ".csv", function(error, dataset) {
dataset.forEach(function(d) {
arrayDateValue.push({
x: d.newdate,
y: d[substanceSelected]
});
});
});
oggetto = {
values: arrayDateValue,
key: key
};
arrayDateValue = [];
final.push(oggetto);
}
}
}
Any idea ?

First you should make the if statement for the city and then for the key, which you seem to be doing wrong since you want the pair indexes to be the keys and the not pair to be the city, and you are doing the opposite. And then you need to have the d3.csv and push the objects outside of the if statement, otherwise in your case you are just adding elements with citySelected="".
Try something like :
for(var i = 0; i < selString.length -1; i+=2){
cittySelected = selString[i];
substanceSelected = selString[i+1];
key = citySelected + "#" + substanceSelected;
d3.csv("/CSV/"+citySelected+".csv", function(error, dataset){
dataset.forEach(function(d){
arrayDateValue.push({x: d.newdate, y: d[substanceSelected]});
});
});
oggetto = {values: arrayDateValue, key: key};
arrayDateValue = [];
final.push(oggetto);
}
It's is not the best way to do it, but it is clearer that what you are following, i think.

In the if(i % 2 == 0) { citySelected = ... } and else if(i % 2 !== 0) { substanceSelected = ... } citySelected and substanceSelected will never come together.
The values should be in one statement:
if(...) { citySelected = ...; substanceSelected = ...; }
The string can be splitted into pairs
city1#substance1, city2#substance2, ...
with a regex (\w{1,}#\w{1,}#).
Empty the arrayDateValue after the if-statement.
Hint:
var str = "cityX#substanceX#cityY#substanceY#";
function createArr(str) {
var obj = {};
var result = [];
var key = "";
// '', cityX#substanceX, '', cityYsubstanceY
var pairs = str.split(/(\w{1,}#\w{1,}#)/g);
for (var i = 0; i < pairs.length; i++) {
if(i % 2 !== 0) {
key = pairs[i];
// d3 stuff to create values
obj = {
// Values created with d3 placeholder
values: [{x: "x", y: "y"}],
// Pair
key: key
};
result.push(obj);
}
// Here should be values = [];
}
return result;
}
var r = createArr(str);
console.log(r);

May be you can do like this;
var str = "cityX#substanceX#cityY#substanceY",
arr = str.split("#").reduce((p,c,i,a) => i%2 === 0 ? p.concat({city:c, key:a[i+1]}) : p,[]);
console.log(JSON.stringify(arr));

RESOLVED-
The problem is about d3.csv which is a asynchronous function, it add in the array when it finish to run all the other code.
I make an XMLHttpRequest for each csv file and it works.
Hope it helps.

Related

Make combinations of elements of an array inside an object

trialObject : {
'color': ['red','blue'],
'size': ['s','m'],
'material': ['cotton']
}
// RECURSION FUNCTION TO MAKE COMBINATIONS
makeObjectVariants(selected){
let key = Object.keys(selected)
if(Object.keys(selected).length === 1){
return selected[key[0]];
} else {
var result = [];
var currentArray = selected[key[0]]
delete selected[key[0]]
var restObjects = this.makeObjectVariants(selected) // call function again
for(var i = 0; i < restObjects.length; i++){
for (var j = 0; j < currentArray.length; j++) {
result.push([restObjects[i] +','+ currentArray[j]]);
}
}
return result; // resultant array
}
}
// OUTPUT
0:["cotton,s,red"]
1:["cotton,s,blue"]
2:["cotton,m,red"]
3:["cotton,m,blue"]
// EXPECTED OUTPUT
[{'material':cotton,'size':s,'color':red},...]
I want the output to contain key value pairs so that the array elements can be recognized which group they fall into.
I am facing problem in adding keys to the elements generated because m unable to keep track of the object keys
If you can use ES6 (default parameters, spread operator, arrow function, ...), the following code do the job:
var trialObject = {
color: ['red','blue'],
size: ['s','m'],
material: ['cotton']
};
var result = buildCombinations(trialObject);
console.log(result);
function buildCombinations(trialObject , keys = Object.keys(trialObject ), keyIndex = 0 , subObj = {}, res = []) {
trialObject[keys[keyIndex]].forEach(element => {
subObj[keys[keyIndex]] = element;
keys[keyIndex + 1] ? buildCombinations(trialObject , keys, keyIndex + 1, subObj, res) : res.push({...subObj});
});
return res;
}

Count in an array the number for each same value

My function is
var MyArray= [];
$('input:checked').each(function(index) {
MyArray= ($(this).attr('id') + ":" + $(this).val()).length;
});
My array is
Array [ "1:R1", "2:R2", "3:R3", "4:R1" ]
I would like to count the differents values and to get this object
Object {R1:2, R2:1, R3:1}
Instead of putting the values in an array and then get the values out of the array to process them and create an object, put them in the object to start with:
var map = {};
$('input:checked').each(function() {
var key = $(this).val();
if (key in map) {
map[key]++;
} else {
map[key] = 1;
}
});
Demo: http://jsfiddle.net/Guffa/0a35c6yp/
You can convert your var with this code :
var arr = [ "1:R1", "2:R2", "3:R3", "4:R1" ];
var obj = {};
for(var i=0, l=arr.length; i<l; i++) {
var parts = arr[i].split(':');
if(parts.length > 1) {
if(!obj[parts[1]]) {
obj[parts[1]] = 0;
}
obj[parts[1]]++
}
}
console.log(obj)
Or create directly the correct object :
var obj = {};
$('input:checked').each(function (index) {
var key = $(this).val();
if (!obj[key]) {
obj[key] = 0;
}
obj[key]++
});
Use a regex to capture the correct portion of the string, and add them as keys to the object, incrementing the value if it already exists:
var regex = /\d+:(R\d+)/
var obj = {};
arr.forEach(function (el) {
var key = el.match(regex)[1];
if (!obj[key]) obj[key] = 0;
obj[key]++;
});
DEMO
You could try something like that:
Write your Array into a Map and step up your value each time your map already knows the key.
for(var i = 0; i < myArray.length; i++){
var entry = myArray[i];
var key = entry.split(":")[1];
if(myMap.has(key))
myMap.set(key, myMap.get(key) + 1);
else
myMap.set(key, 1);
}
DEMO

remove duplicated value from array and replace it with the latest value in javascript

I have an array in JavaScript. The user enters string and the data placed in this array in the form of value and name.
if(!_.isUndefined(args[1]) && !_.isUndefined(args[2])) {
if(args[1].length !== 0 && args[2].length !== 0) {
var dataObj = {
name : args[1],
value : args[2]
};
formateArray.push({name: dataObj.name, value:dataObj.value});
How can I remove duplicated value from array and replace it with the latest value the user enters?
So when the user enters: value_1 100, value_2 200, value_1 500
I expect to see: value_1 500, value_2 200 (replace the duplicates with new data)
You can iterate your array replace the value if the name already exists.
function push(array, newVal) {
var found = false;
for (var i = 0; i < array.length && !found; i++) {
if (array[i].name === newVal.name) {
array[i].value = newVal.value;
found = true;
}
}
if (!found) {
array.push(newVal);
}
}
function printNameValue(array) {
var out = '';
for (var i = 0; i < array.length; i++) {
out += array[i].name + ' ' + array[i].value + ', ';
}
return out;
}
var myArray = [];
push(myArray, {
name: 'value_1',
value: 100
});
push(myArray, {
name: 'value_2',
value: 200
});
push(myArray, {
name: 'value_1',
value: 500
});
alert(printNameValue(myArray));
Since your values can be associated with meaningful keys, perhaps you should use an object map rather than an array to store your values. Avoiding duplicates now becomes trivial since you cannot have duplicate keys.
var valuesMap = {};
//setting value
valuesMap.value_1 = 100;
//setting another value
valuesMap.value_2 = 200;
//replacing it
valuesMap.value_1 = 500;
Otherwise it's still quite simple, but less efficient:
function add(arr, obj) {
var key = obj.name, i, len;
for (i = 0, len = arr.length; i < len; i++) {
if (arr[i].name === key) {
arr[i] = obj;
return;
}
}
arr.push(obj);
}
var values = [];
add(values, { name: 'test', value: 1 });
add(values, { name: 'test', value: 2 });
values.length; //1
Instead of the array object, i suggest you to use an object that will act like a hashtable. You can define on this way var formateArray = {};
When you want to add or edit the data, instead of using push, you can do it like this:
formateArray[dataObj.name] = {name: dataObj.name, value:dataObj.value};
If the key does not exist dataObj.name, it will be added. It the key exist, the value would set with the new value.
If you want the size of you array, you get it this way Object.keys(formateArray).length
If you want to loop on your data, you can do it this way:
for (var k in formateArray) {
// use hasOwnProperty to filter out keys from the Object.prototype
if (formateArray.hasOwnProperty(k)) {
alert('key is: ' + k + ', value is: ' + formateArray[k].value);
}
}
Here is a jsfiddle that illustrate this.

String split and count the number of occurrences and also

I have a string
var stringIHave = "Java$$Java$$jQuery$$Java$$jQuery$$Java$$Java$$Java$$Hibernate$$Java$$Java$$Spring$$Instagram$$jQuery$$jQuery$$";
How to get the count of the number of occurrences of each entry, The occurrence I get, is from a JSON like Java = 8 and etc...
First of all you need to split your srting to array:
var keywordsArr = stringIHave.split( '$$' );
then you need to have an object for example to store counts:
var occur = {};
and then just create simple for loop to count all occurrences:
for( var i = 0; i < keywordsArr.length; i++ ) {
occur[ keywordsArr[ i ] ] = ( occur[ keywordsArr[ i ] ] || 0 ) + 1;
}
now your object occur will have names as keys and count as values.
See jsFiddle demo.
Also as you have at end of your string $$ you maybe will need to remove last item from keywordsArr so just do after split function call:
keywordsArr.pop();
See demo without last element.
So final code will be like:
var stringIHave = "Java$$Java$$jQuery$$Java$$jQuery$$Java$$Java$$Java$$Hibernate$$Java$$Java$$Spring$$Instagram$$jQuery$$jQuery$$",
keywordsArr = stringIHave.split( '$$' ),
occur = {};
keywordsArr.pop();
for( var i = 0; i < keywordsArr.length; i++ ) {
occur[ keywordsArr[ i ] ] = ( occur[ keywordsArr[ i ] ] || 0 ) + 1;
}
for( var key in occur ) {
document.write( key + ' - ' + occur[key] + '<br/>' );
} ​
I'd suggest the following:
function stringCount(haystack, needle) {
if (!needle || !haystack) {
return false;
}
else {
var words = haystack.split(needle),
count = {};
for (var i = 0, len = words.length; i < len; i++) {
if (count.hasOwnProperty(words[i])) {
count[words[i]] = parseInt(count[words[i]], 10) + 1;
}
else {
count[words[i]] = 1;
}
}
return count;
}
}
console.log(stringCount("Java$$Java$$jQuery$$Java$$jQuery$$Java$$Java$$Java$$Hibernate$$Java$$Java$$Spring$$Instagram$$jQuery$$jQuery$$", '$$'));
​
JS Fiddle demo.
References:
Object.hasOwnProperty().
parseInt().
String.split().
It's not entirely clear what final objective is. Following creates an object from string that looks like
Object created:
{
"Java": 8,
"jQuery": 4,
"Hibernate": 1,
"Spring": 1,
"Instagram": 1
}
JS:
var str = 'Java$$Java$$jQuery$$Java$$jQuery$$Java$$Java$$Java$$Hibernate$$Java$$Java$$Spring$$Instagram$$jQuery$$jQuery$$';
var arr = str.split('$$')
var obj = {};
for (i = 0; i < arr.length; i++) {
if (arr[i] != '') {
if (!obj[arr[i]]) {
obj[arr[i]] = 0;
}
obj[arr[i]]++;
}
}
You can loop over the object to get all values or simply look up one value
var jQueryOccurences= obj['jQuery'];
DEMO: http://jsfiddle.net/25hBV/1/
Now a days you can do
const str = "Java$$Java$$jQuery$$Java$$jQuery$$Java$$Java$$Java$$Hibernate$$Java$$Java$$Spring$$Instagram$$jQuery$$jQuery$$";
var result = str.split("$$").reduce(function(acc, curr) {
curr && (acc[curr] = (acc[curr] + 1) || 1);
return acc
}, {});
console.log(result);
Split the string into an array, and putting the array into an object takes care of duplicates and counts occurences as key/value pairs in the object, see fiddle!
var stringIHave = "Java$$Java$$jQuery$$Java$$jQuery$$Java$$Java$$Java$$Hibernate$$Java$$Java$$Spring$$Instagram$$jQuery$$jQuery$$",
s = stringIHave.split('$$');
obj = {};
for (var i=s.length; i--;) {
obj[s[i]] = (s[i] in obj) ? obj[s[i]]+1 : 1;
}
// obj.Java == 8
FIDDLE
If you want it short and sweet:
// variable declarations
var arParts = stringIHave.match(/\w+/g),
result = {},
i = 0,
item;
// Copy the array to result object
while (item = arParts[i++]) result[item] = (result[item] || 0 ) + 1;
demo

Javascript Multidimensional Array: Add Values

So I have a multidimensional array like:
myArr = [["venue",2],["venue",16],["inning",2],["inning",4],["inning",32],["hithard", 4]]
I would like to add the similar values up. So in the end I just have:
"venue" = 18, "inning" = 38, and "hithard" = 4.
Can you give me an example of how to accomplish this? Either with Javascript and/or jQuery
Thanks!
I am not sure if you want an array or object. If object, stop it is 1st pass and tmp in below code should return you the object as Object { venue=18, inning=38, hithard=4}.
DEMO
var tmp = {}, keys;
for (var i = 0; i < myArr.length; i++) {
keys = myArr[i][0];
tmp[keys] = (tmp.hasOwnProperty(keys))?
(tmp[keys] + myArr[i][1]):myArr[i][1];
} //tmp - will return you a Object { venue=18, inning=38, hithard=4}
var output = [];
for (keys in tmp) {
output.push([keys, tmp[keys]]);
} //output will return you an array as [["venue", 18],["inning", 38],["hithard", 4]]
myArr = [["venue",2],["venue",16],["inning",2],["inning",4],["inning",32],["hithard", 4]];
values = {};
for (i=0;i<myArr.length;i++){
if ("undefined" == typeof values[myArr[i][0]]) {values[myArr[i][0]] = 0;}
values[myArr[i][0]] += myArr[i][1];
}
arr = [];
query_string = "";
for (i in values) {
// if you want it in an array:
arr.push('"' + i + '" = ' + values[i]);
query_string += (query_string.length ? "&" : "") + i + "=" + values[i];
}
​console.log(arr);​
DEMO: http://jsfiddle.net/Ta97E/2/
you can use values to create the query string
Check this code:
var final = {};
for (var i in myArr) {
var item = myArr[i];
final[item[0]] = (final[item[0]] || 0) + item[1];
}
console.log(final);​
DEMO: http://jsfiddle.net/UVJEb/
Underscore solution:
sums = _.reduce(myArr, function (obj, item) {
obj[item[0]] = (obj[item[0]] || 0) + item[1];
return obj;
}, {});
// sums = {"venue":18,"inning":38,"hithard":4}
A little dirtier in jQuery
sums = {}
$.each(myArr, function (i, value) {
sums[value[0]] = (sums[value[0]] || 0) + value[1];
});
Edit: add jQuery version

Categories

Resources