Removing duplicates and summing up quantity - javascript

var name = new Array();
var amount = new Array();
name[0]="Peter";
amount[0]="50";
name[1]="John";
amount[1]="10";
name[2]="John";
amount[2]="20";
name[3]="Peter";
amount[3]="20";
name[4]="Mary";
amount[4]="40";
I have something like the above. My question is, how can I create a function to eliminate all the duplicates and sum up the values for each person in the arrays? Below is the results I am looking for.
For example:
Peter 70
John 30
Mary 40

Try the following
var sum = {};
var i;
for (i = 0; i < amount.length; i++) {
var name = name[i];
var oldSum = sum[name];
if (typeof oldSum === 'undefined') {
oldSum = 0;
}
sum[name] = oldSum + amount[i];
}
Now the object sum will have a property for every name in name and the value of the property will be the sum of the amounts which had the that name
To print it out try the following
for (var prop in sum) {
if (sum.hasOwnProperty(prop)) {
console.log(prop + " " sum[prop]);
}
}

result = {};
for( var i=name.length; i--; ) {
result[name[i]] = result[ name[i] ] ? (result[name[i]] + parseInt( amount[i], 10 )) : parseInt( amount[i], 10 );
}
console.log( result );
returns
{ Mary=40, Peter=70, John=30 }
The parseInt() is just necessary as you give the amount[] values as strings.
result after the call is an object holding the summed up values, where the key is the entry from name[] and the value is from amount[].

tally=[];
for(i=0;i<name.length;i++) {
if(tally[name[i]]==undefined){
tally[name[i]]=parseInt(amount[i]);
}else{
tally[name[i]]+=parseInt(amount[i]);
}
}

I can't tell if you actually want to modify the Arrays, or just collect the results.
Here's a way to collect the results in an Object.
var result = name.reduce(function(res, n, i) {
res[n] = (res[n] + +amount[i]) || +amount[i];
return res;
}, {});
The .reduce() method requires a shim for IE8 and lower.
Result is:
{
"Peter": 70,
"John": 30,
"Mary": 40
}

Related

How to find the most duplicate "values" in javascript array?

my question is actually similar to: Extracting the most duplicate value from an array in JavaScript (with jQuery)
I Found this but it always return one value only which is 200.
var arr = [100,100,200,200,200,300,300,300,400,400,400];
var counts = {}, max = 0, res;
for (var v in arr) {
counts[arr[v]] = (counts[arr[v]] || 0) + 1;
if (counts[arr[v]] > max) {
max = counts[arr[v]];
res = arr[v];
}
}
console.log(res + " occurs " + counts[res] + " times");
pls help me to return values not just one...
The result is should like this:
200,300,400
.
pls help thank you!
You have to iterate your counts to find the max occurred result.
var arr = [100,100,200,200,200,300,300,300,400,400,400];
var counts = {}, max = 0, res;
for (var v in arr) {
counts[arr[v]] = (counts[arr[v]] || 0) + 1;
if (counts[arr[v]] > max) {
max = counts[arr[v]];
res = arr[v];
}
}
var results = [];
for (var k in counts){
if (counts[k] == max){
//console.log(k + " occurs " + counts[k] + " times");
results.push(k);
}
}
console.log(results);
Create a Object iterating the arry containing the indexes of most repeated values, like below
var arr = [100,100,200,200,200,300,300,300,400,400,400];
valObj = {}, max_length = 0, rep_arr = [];
arr.forEach(function(el,i){
if(valObj.hasOwnProperty(el)){
valObj[el] += 1;
max_length = (valObj[el] > max_length) ? valObj[el] : max_length
}
else{
valObj[el] = 1;
}
});
Object.keys(valObj).forEach(function(val){
(valObj[val] >= max_length) && (rep_arr.push(val))
});
console.log(rep_arr);
After the object is created with key as array value and value as array indexes of that value, you can play/parse that. Hope this helps.
Iterating an array using for..in is not a good idea. Check this link for more information.
Hopefully below snippet will be useful
var arr = [100, 100, 200, 200, 200, 300, 300, 300, 400, 400, 400];
//Use a reduce fuction to create an object where 100,200,300
// will be keys and its value will the number of times it has
//repeated
var m = arr.reduce(function(i, v) {
if (i[v] === undefined) {
i[v] = 1
} else {
i[v] = i[v] + 1;
}
return i;
}, {});
// Now get the maximum value from that object,
//getMaxRepeated will be 3 in this case
var getMaxRepeated = Math.max(...Object.values(m));
//An array to hold elements which are repeated 'getMaxRepeated' times
var duplicateItems = [];
// now iterate that object and push the keys which are repeated
//getMaxRepeated times
for (var keys in m) {
if (m[keys] === getMaxRepeated) {
duplicateItems.push(keys)
}
}
console.log(duplicateItems)
The following would do the trick assuming that all items in arr are numbers:
//added some numbers assuming numbers are not sorted
var arr = [300,400,200,100,100,200,200,200,300,300,300,400,400,400];
var obj = arr.reduce(//reduce arr to object of: {"100":2,"200":4,"300":4,"400":4}
(o,key)=>{//key is 100,200, ... o is {"100":numberOfOccurrences,"200":numberOf...}
o[key] = (o[key])?o[key]+1:1;
return o;
},
{}
);
// obj is now: {"100":2,"200":4,"300":4,"400":4}
//create an array of [{key:100,occurs:2},{key:200,occurs:4}...
var sorted = Object.keys(obj).map(
key=>({key:parseInt(key),occurs:obj[key]})
)//sort the [{key:100,occurs:2},... by highest occurrences then lowest key
.sort(
(a,b)=>
(b.occurs-a.occurs===0)
? a.key - b.key
: b.occurs - a.occurs
);
console.log(
sorted.filter(//only the highest occurrences
item=>item.occurs===sorted[0].occurs
).map(//only the number; not the occurrences
item=>item.key
)
);
Try as following ==>
function getDuplicate( arr ){
let obj = {}, dup = [];
for(let i = 0, l = arr.length; i < l; i++){
let val = arr[i];
if( obj[val] /**[hasOwnProperty]*/ ) {
/**[is exists]*/
if(dup.find(a => a == val) ) continue;
/**[put Unique One]*/
dup.push(val);
continue;
};
/**[hold for further use]*/
obj[val] = true;
}
return dup;
};
Use ==>
getDuplicate([100,100,200,200,200,300,300,300,400,400,400]);
Try the following:
var candles = [100,100,200,200,200,300,300,300,400,400,400];
let tempArray = {}
for (let index = 0; index <= (candles.length - 1); index++) {
let valueToCompare = candles[index];
if (tempArray[valueToCompare]) {
tempArray[valueToCompare] = tempArray[valueToCompare] + 1;
} else {
tempArray[valueToCompare] = 1;
}
}
let highestValue;
Object.values(tempArray).forEach(item => {
if (highestValue === undefined) highestValue = item;
if (highestValue < item) highestValue = item;
});
console.log(highestValue);

Push different object in an array with a for loop

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.

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.

Iterate through an array and return how many of each is present in jquery

So I have an array. The array has string values inside that can change each time:
var array = ['1','2','3','4','5'];
or sometimes:
var array = ['1','4','3','4','4'];
or even:
var array = ['1','3','3','4','4'];
How would I go about iterating through this array, figuring out which value is present the most and then displaying it. Also, how would I go about making it even smarter to understand that sometimes there is a tie between two values, as is the case in the last array above, and then displaying info notifying me that values "3" and "4" are tied... Or if there is no value that occurs more than once, thus displaying all values. Thoughts?
function findMostFrequent(array) {
// {
// "valueInTheArray": numberOfOccurances,
// ...
// }
var data = {};
// for each value in the array increment the number of
// occurences for that value. the or clause defaults it to 0.
$.each(array, function(i, val) {
data[val] = data[val]++ || 1;
});
var answer = null;
// for each value if the occurances is higher then to the counter.
// then set that as the counter.
$.each(data, function(key, val) {
if (val > data[answer]) answer = key;
}
return answer;
}
You need two loops. One to count how many times each value occured. And one to find which one occured the most.
Optionally if you want to handle multiple high values then replace the second loop with this.
var answer = [null];
// for each value if the occurances is equal then add it to the array
// else if the occurance is higher then the current highest occurance.
// then set that as the current array of values.
$.each(data, function(key, val) {
if (val === data[answer[0]]) {
answer.push(key);
} else if (val > data[answer[0]]) {
answer = [key];
}
}
return answer;
Try this:
var array = ['1','2','3', '3','4','5', '3', '4', '5', '5'],
l = array.length,
col = {},
current,
max = {cnt:0, values:[]};
while(l--){
current = array[l];
col[current] = (col[current] || 0) + 1;
if(col[current] > max.cnt){
max = {cnt:col[current], values: [current]};
}else if(col[current] === max.cnt){
max.values.push(current);
}
}
console.log(
max.cnt === 1 ?
'they are all different' :
max.values.join(',') + ' occured ' + max.cnt + ' times'
);
You probably want to use something like this:
var arr = [5, 5, 5, 2, 2, 2, 2, 2, 9, 4];
var counts = {};
for(var i = 0; i< arr.length; i++) {
var num = arr[i];
counts[num] = counts[num] ? counts[num]+1 : 1;
}
Now, you'll have an object that has a count of all the members in the array.
console.log(counts[5]); // logs '3'

array_count_values for JavaScript instead

I have the following PHP-script, now I need to do the same thing in JavaScript. Is there a function in JavaScript that works similar to the PHP function, I have been searching for days but cannot find anything similar? What I want to do is to count the number of times a certain word is being used in an array.
$interfaceA = array($interfaceA_1,$interfaceA_2,$interfaceA_3,$interfaceA_4,$interfaceA_5,$interfaceA_6,$interfaceA_7,$interfaceA_8);
$interfaceA_array=array_count_values($interfaceA);
$knappsatsA = $interfaceA_array[gui_knappsats];
$touchpanelA = $interfaceA_array[gui_touchpanel];
Why not simply create a new javascript array "counts"
Iterate over original array, and increament the count of "counts" for keys encountered in the array.
http://jsfiddle.net/4t28P/1/
var myCurrentArray = new Array("apple","banana","apple","orange","banana","apple");
var counts = {};
for(var i=0;i< myCurrentArray.length;i++)
{
var key = myCurrentArray[i];
counts[key] = (counts[key])? counts[key] + 1 : 1 ;
}
alert(counts['apple']);
alert(counts['banana']);
Another elegant solution would be to use Array.prototype.reduce.
Given:
var arr = new Array("apple","banana","apple","orange","banana","apple");
You can just run reduce on it:
var groups =
arr.reduce(function(acc,e){acc[e] = (e in acc ? acc[e]+1 : 1); return acc}, {});
Finally you can check the result:
groups['apple'];
groups['banana'];
In the sample above reduce takes two parameters:
a function (anonymous here) taking an accumulator (initialized from the second argument of reduce), and the current array element
the initial value of the accumulator
Whatever the function returns, it will be used as the accumulator value in the next call.
From a type perspective, whatever the type of the array elements, the type of the accumulator must match the type of the second argument of reduce (initial value), and the type of the return value of the anonymous function.
This will also be the type of the return value of reduce.
Try
a.reduce((a,c)=> (a[c]=++a[c]||1,a) ,{});
let a= ["apple","banana","apple","orange","banana","apple"];
let count= a.reduce((a,c)=> (a[c]=++a[c]||1,a) ,{});
console.log(count);
How about this:
function arrayCountValues (arr) {
var v, freqs = {};
// for each v in the array increment the frequency count in the table
for (var i = arr.length; i--; ) {
v = arr[i];
if (freqs[v]) freqs[v] += 1;
else freqs[v] = 1;
}
// return the frequency table
return freqs;
}
let snippet = "HARRY POTTER IS A SERIES OF FANTASY NOVELS WRITTEN BY BRITISH AUTHOR J. K. ROWLING. THE NOVELS CHRONICLE" +
" THE LIVES OF A YOUNG WIZARD, HARRY POTTER , AND HIS FRIENDS HERMIONE GRANGER AND RON WEASLEY, ALL OF WHOM ARE " +
" STUDENTS AT HOGWARTS SCHOOL OF WITCHCRAFT AND WIZARDRY";
String.prototype.groupByWord = function () {
let group = {};
this.split(" ").forEach(word => {
if (group[word]) {
group[word] = group[word] + 1;
} else {
group[word] = 1;
}
});
return group;
};
let groupOfWordsByCount = snippet.groupByWord();
console.log(JSON.stringify(groupOfWordsByCount,null, 4))
This should work
function array_count_values(array) {
var tmpArr = {};
var key = '';
var t = '';
var _countValue = function(tmpArr, value) {
if (typeof value === 'number') {
if (Math.floor(value) !== value) {
return;
}
} else if (typeof value !== 'string') {
return;
}
if (value in tmpArr && tmpArr.hasOwnProperty(value)) {
++tmpArr[value];
} else {
tmpArr[value] = 1;
}
}
for (key in array) {
if (array.hasOwnProperty(key)) {
_countValue.call(this, tmpArr, array[key]);
}
}
return tmpArr;
}
console.log(array_count_values([12, 43, 12, 43, "null", "null"]));

Categories

Resources