How to find sum of duplicate values in an array using javascript - javascript

I have the following array with me. And my aim is to create a new array by removing duplicate values from this array.
var xDataValuesdash = [ [ 'Anantapur', 10, '#C21466' ],
[ 'Anantapur', 20, '#A983D0' ],
[ 'Chittoor', 30, '#A993D0' ],
[ 'Anantapur', 30, '#544DDF' ],
[ 'Anantapur', 4, '#A994D0' ],
[ 'Chittoor', 40, '#544BDF' ] ];
ie, The resultant array must be
var new_xDataValuesdash = [[ 'Anantapur', 64, '#C21466' ],
[ 'Chittoor', 70, '#544BDF' ]];
While removing duplicates its value must be added to the unqiue value.

Try this
var xDataValuesdash = [ [ 'Anantapur', 10, '#C21466' ],
[ 'Anantapur', 20, '#A983D0' ],
[ 'Chittoor', 30, '#A993D0' ],
[ 'Anantapur', 30, '#544DDF' ],
[ 'Anantapur', 4, '#A994D0' ],
[ 'Chittoor', 40, '#544BDF' ] ];
var sum = {},result;
for (var i=0,c;c=xDataValuesdash[i];++i) {
if ( undefined === sum[c[0]] ) {
sum[c[0]] = c;
}
else {
sum[c[0]][1] += c[1];
}
}
result = Object.keys(sum).map(function(val) { return sum[val]});
alert(JSON.stringify(result));

Here is a simple solution, not very sophisticated but gets the job done.
var a = [
['Anantapur', 10, '#C21466'],
['Anantapur', 20, '#A983D0'],
['Chittoor', 30, '#A993D0'],
['Anantapur', 30, '#544DDF'],
['Anantapur', 4, '#A994D0'],
['Chittoor', 40, '#544BDF']
];
var findDuplicatesAndSum = function(inptArr) {
var duplicateIndex = {};
var outputArr = [];
for (var i = 0; i < inptArr.length; i++) {
var item = inptArr[i];
var collisionIndex = duplicateIndex[item[0]];
if (collisionIndex > -1) {
outputArr[collisionIndex][1] += item[1];
} else {
outputArr.push(item);
duplicateIndex[item[0]] = outputArr.length - 1;
}
}
console.log(outputArr);
return outputArr;
};
findDuplicatesAndSum(a);

This code might helps.
var xDataValuesdash = [
[ 'Anantapur', 10, '#C21466' ],
[ 'Anantapur', 20, '#A983D0' ],
[ 'Chittoor', 30, '#A993D0' ],
[ 'Anantapur', 30, '#544DDF' ],
[ 'Anantapur', 4, '#A994D0' ],
[ 'Chittoor', 40, '#544BDF' ] ];
var new_DataValuesdash = [];
for(var i=0; i < xDataValuesdash.length;i++){
if(new_DataValuesdash[xDataValuesdash[i][0]] == undefined) {
new_DataValuesdash[xDataValuesdash[i][0]] = xDataValuesdash[i];
}
else {
// new_DataValuesdash[xDataValuesdash[i][0]] = [];
new_DataValuesdash[xDataValuesdash[i][0]][1] = new_DataValuesdash[xDataValuesdash[i][0]][1] + xDataValuesdash[i][1];
}
}
console.log(new_DataValuesdash);

You can use for..of loop, Array.prototype.some(), Array.prototype.forEach()
var xDataValuesdash = [ [ 'Anantapur', 10, '#C21466' ],
[ 'Anantapur', 20, '#A983D0' ],
[ 'Chittoor', 30, '#A993D0' ],
[ 'Anantapur', 30, '#544DDF' ],
[ 'Anantapur', 4, '#A994D0' ],
[ 'Chittoor', 40, '#544BDF' ] ];
var res = [];
for (var prop of xDataValuesdash) {
!res.some(value => value && value[0] === prop[0])
? res.push(prop)
: res.forEach(value => {
if (value[0] === prop[0]) value[1] += prop[1]
});
}
console.log(res);

Related

Create array data structure from nested object of arrays in JS

I have a data structure as follows:
UPDATED: to have more than one object in innerValues
const data = {
"dates": [
"2015-09-09T00:00:00",
"2015-09-09T00:10:00",
"2015-09-09T00:20:00",
],
"innerValues": [
{
"name": "Name_1",
"value": [
104,
105,
107,
]
},
{
"name": "Name_2",
"value": [
656,
777,
145,
]
}],
}
I would like to create an output like:
const outPut = [
["2015-09-09T00:00:00", 'Name_1', 104 ],
["2015-09-09T00:10:00", 'Name_1', 105 ],
["2015-09-09T00:20:00", 'Name_1', 107 ],
["2015-09-09T00:00:00", 'Name_2', 104 ],
["2015-09-09T00:10:00", 'Name_2', 105 ],
["2015-09-09T00:20:00", 'Name_2', 107 ]
]
So far I have this, I know I could do this with forEach etc also - but as an example.
const m = data.dates;
let arr = [];
for (var i = 0; i < m.length; i++) {
arr[i] = new Array(m[i]);
}
console.log(arr);
This gives:
0: ['2021-09-09T00:00:00']
1: ['2021-09-09T00:10:00']
2: ['2021-09-09T00:20:00']
Which is where I want to start, however if I map over inner.values and try to create an new array from that, it does not return three separate arrays but one.e.g
const newArray = x.forEach(inner => console.log(new Array(inner)))
Output
0: (3) [104, 105, 107]
How could I achieve the above desired structure.
You can use reduce and map to loop over innerValues and their values
const dates = data.dates
const newArr = data.innerValues.reduce((acc, cur, i) => {
acc.push(cur.value.map((value, i) => ([dates[i], cur.name, value])));
return acc;
}, []).flat()
console.log(newArr)
<script>
const data = {
"dates": [
"2015-09-09T00:00:00",
"2015-09-09T00:10:00",
"2015-09-09T00:20:00",
],
"innerValues": [{
"name": "Name_1",
"value": [
104,
105,
107,
]
},
{
"name": "Name_2",
"value": [
656,
777,
145,
]
}
],
}
</script>

Confused about pushing array into array, JavaScript

My code looks like this
var res = [];
var temp = [];
function Permutations(target, size) {
if (size === 0) {
res.push(temp);
console.log(res);
return;
}
for (let i = 0; i < target.length; i++) {
if (target[i] !== null) {
temp.push(target[i]);
target[i] = null;
Permutations(target, size - 1);
target[i] = temp.pop();
}
}
}
Permutations([1, 2, 3], 2);
console.log(res);
When I run my code, I can see my res stores each permutation as it is is being executed. However, when I log it outside the function, all the stored value disappeared.
[ [ 1, 2 ] ]
[ [ 1, 3 ], [ 1, 3 ] ]
[ [ 2, 1 ], [ 2, 1 ], [ 2, 1 ] ]
[ [ 2, 3 ], [ 2, 3 ], [ 2, 3 ], [ 2, 3 ] ]
[ [ 3, 1 ], [ 3, 1 ], [ 3, 1 ], [ 3, 1 ], [ 3, 1 ] ]
[ [ 3, 2 ], [ 3, 2 ], [ 3, 2 ], [ 3, 2 ], [ 3, 2 ], [ 3, 2 ] ]
[ [], [], [], [], [], [] ] // This is my console.log outside the function
The array temp holds is the same array throughout the complete execution of your code. And res.push(temp); adds this same array (not a copy of it) to your res array.
Here a related question about how Objects are handled in JavaScript: Is JavaScript a pass-by-reference or pass-by-value language?
So your code results in res having N times the same array.
You could copy the element stored in temp to a new array using [...temp], and push that to your res array.
var res = [];
var temp = [];
function Permutations(target, size) {
if (size === 0) {
res.push([...temp]);
return;
}
for (let i = 0; i < target.length; i++) {
if (target[i] !== null) {
temp.push(target[i]);
target[i] = null;
Permutations(target, size - 1);
target[i] = temp.pop();
}
}
}
Permutations([1, 2, 3], 2);
console.log(res);

How to do Math.random() in for-loop with different values?

I try to fill the array s with 9999 different sets of values m[i][random], here is the code:
let m = [[22,0],[53,0],[64,0],[45,0],[34,0]];
let l = m.length;
let s = [];
for (let j = 0; j < 9999; j++)
{
for(let i = 0; i < m.length; i++)
{
let x = Math.floor(Math.random()*l);
m[i][1] = x;
}
s.push(m);
}
But i get the same values:
console.log(s)
[ [ [ 22, 0 ], [ 53, 2 ], [ 64, 0 ], [ 45, 4 ], [ 34, 1 ] ],
[ [ 22, 0 ], [ 53, 2 ], [ 64, 0 ], [ 45, 4 ], [ 34, 1 ] ],
[ [ 22, 0 ], [ 53, 2 ], [ 64, 0 ], [ 45, 4 ], [ 34, 1 ] ],
[ [ 22, 0 ], [ 53, 2 ], [ 64, 0 ], [ 45, 4 ], [ 34, 1 ] ],
[ [ 22, 0 ], [ 53, 2 ], [ 64, 0 ], [ 45, 4 ], [ 34, 1 ] ],
[ [ 22, 0 ], [ 53, 2 ], [ 64, 0 ], [ 45, 4 ], [ 34, 1 ] ],
[ [ 22, 0 ], [ 53, 2 ], [ 64, 0 ], [ 45, 4 ], [ 34, 1 ] ], ...]
What am I doing wrong? How to fix it?
Create the m subarray inside the loop (so you have a separate subarray for each iteration), not outside of it - outside, you've only created a single array in memory that each index points to.
let s = [];
for (let j = 0; j < 9999; j++)
{
let m = [[22,0],[53,0],[64,0],[45,0],[34,0]];
let l = m.length;
for(let i = 0; i < m.length; i++)
{
let x = Math.floor(Math.random()*l);
m[i][1] = x;
}
s.push(m);
}
Or, more functionally and all at once with Array.from:
const s = Array.from(
{ length: 2 },
() => [[22,0],[53,0],[64,0],[45,0],[34,0]]
.map(([num]) => [num, Math.floor(Math.random() * 5)])
);
console.log(s);

My for loop is not working properly however I have no idea why

So basically I'm writing a script that takes in a credit card number and outputs the provider name. (Also if im doing this in an overly complicated way advice is appreciated)
But my initial for loop to iterate over each object is not working. It will get to 3 (even though the length of the arr is 8) and then just stop...
I am dumbfounded as I have re-read the code for an hour now, checked everything I could think of but am just hitting a wall. Any help would be much appreciated!
The Code
var detectNetwork = function(cardNumber) {
var splitDigits = cardNumber.split('');
var length = splitDigits.length;
var first = splitDigits[0];
var second = splitDigits[1];
var firstTwo = splitDigits[0] + splitDigits[1];
var firstThree = splitDigits[0] + splitDigits[1] + splitDigits[2];
var firstFour = splitDigits[0] + splitDigits[1] + splitDigits[2] + splitDigits[3];
var firstSix = splitDigits[0] + splitDigits[1] + splitDigits[2] + splitDigits[3] + splitDigits[4] + splitDigits[5];
var checkProvider = [
{
name: 'American Express',
length: [ 15 ],
prefixLength: [ 2 ],
prefixType: 'simple',
prefix: [ 34, 37 ]
},
{
name: 'Diner\'s Club',
length: [ 14 ],
prefixLength: [ 2 ],
prefixType: 'simple',
prefix: [ 38, 39 ]
},
{
name: 'Visa',
length: [ 13, 16, 19 ],
prefixLength: [ 1 ],
prefixType: 'simple',
prefix: [ 4 ]
},
{
name: 'MasterCard',
length: [ 16 ],
prefixLength: [ 2 ],
prefixType: 'range',
prefix: [ 51, 55 ]
},
{
name: 'Discover',
length: [ 16, 19 ],
prefixLength: [ 2, 3, 4],
prefixType: 'complexRange',
prefix: [ 6011, [ 644, 649 ], 65 ]
},
{
name: 'Maestro',
length: [ 12, 13, 14, 15, 16, 17, 18, 19],
prefixLength: [ 4 ],
prefixType: 'simple',
prefix: [ 5018, 5020, 5038, 6304 ]
},
{
name: 'China UnionPay',
length: [ 16, 17, 18, 19 ],
prefixLength: [ 3, 4, 6 ],
prefixType: 'complexRange',
prefix: [ [ 622126, 622925 ], [ 624, 626 ], [ 6282, 6288 ] ]
},
{
name: 'Switch',
length: [ 16, 18, 19 ],
prefixLength: [ 4, 6 ],
prefixType: 'simple',
prefix: [ 4903, 4905, 4911, 4936, 564182, 633110, 6333, 6759 ]
}
];
for(var i = 0; i < checkProvider.length; i++) {
var currentProvider = checkProvider[i];
var name = currentProvider.name;
var lengthOptions = currentProvider.length;
var prefixLengthOptions = currentProvider.prefixLength;
var prefixType = currentProvider.prefixType;
var prefixOptions = currentProvider.prefix;
for(var j = 0; j < lengthOptions.length; j++) {
var currentLength = lengthOptions[j];
if (currentLength === length) {
//Use first
for (var y = 0; y < prefixLengthOptions.length; y++) {
var currentPrefixLength = prefixLengthOptions[y];
if(currentPrefixLength === 1) {
if (first === '4') {
if (firstFour !== 4903 && firstFour !== 4905 && firstFour !== 4911 && firstFour !== 4936) {
return name;
}
}
}
if (currentPrefixLength === 2) {
if (prefixType === 'complexRange') {
console.log(name);
}
if (prefixType === 'simple') {
for (var i = 0; i < prefixOptions.length; i++) {
if (firstTwo === prefixOptions[i].toString()) {
return name;
}
}
}
if (prefixType === 'range') {
var min = prefixOptions[0];
var max = prefixOptions[1];
for (var i = min; i < max + 1; i++) {
if (firstTwo === i.toString()) {
return name;
}
}
}
}
}
}
}
}
}
Your test detectNetwork('6011123456789303') logs Discover if you make the following small changes to your code:
Replace all var with const.
Declare all loop index variables with let. For example, for (let i = 0;.
The issue with your current code is that you have var i redeclared within the same context. According to documentation, these cases do not trigger an error, however the behavior will be confusing when the values are overwritten, which is your case.
The suggestion is to rename the other var i to something else, and that should solve your problem.
Another option is to use let i which will make the context more strict.
So this code would work best (I made it so if always returns the name):
const detectNetwork = function(cardNumber) {
const splitDigits = cardNumber.split('');
const length = splitDigits.length;
const first = splitDigits[0];
const second = splitDigits[1];
const firstTwo = splitDigits[0] + splitDigits[1];
const firstThree = splitDigits[0] + splitDigits[1] + splitDigits[2];
const firstFour = splitDigits[0] + splitDigits[1] + splitDigits[2] + splitDigits[3];
const firstSix = splitDigits[0] + splitDigits[1] + splitDigits[2] + splitDigits[3] + splitDigits[4] + splitDigits[5];
const checkProvider = [
{
name: 'American Express',
length: [ 15 ],
prefixLength: [ 2 ],
prefixType: 'simple',
prefix: [ 34, 37 ]
},
{
name: 'Diner\'s Club',
length: [ 14 ],
prefixLength: [ 2 ],
prefixType: 'simple',
prefix: [ 38, 39 ]
},
{
name: 'Visa',
length: [ 13, 16, 19 ],
prefixLength: [ 1 ],
prefixType: 'simple',
prefix: [ 4 ]
},
{
name: 'MasterCard',
length: [ 16 ],
prefixLength: [ 2 ],
prefixType: 'range',
prefix: [ 51, 55 ]
},
{
name: 'Discover',
length: [ 16, 19 ],
prefixLength: [ 2, 3, 4],
prefixType: 'complexRange',
prefix: [ 6011, [ 644, 649 ], 65 ]
},
{
name: 'Maestro',
length: [ 12, 13, 14, 15, 16, 17, 18, 19],
prefixLength: [ 4 ],
prefixType: 'simple',
prefix: [ 5018, 5020, 5038, 6304 ]
},
{
name: 'China UnionPay',
length: [ 16, 17, 18, 19 ],
prefixLength: [ 3, 4, 6 ],
prefixType: 'complexRange',
prefix: [ [ 622126, 622925 ], [ 624, 626 ], [ 6282, 6288 ] ]
},
{
name: 'Switch',
length: [ 16, 18, 19 ],
prefixLength: [ 4, 6 ],
prefixType: 'simple',
prefix: [ 4903, 4905, 4911, 4936, 564182, 633110, 6333, 6759 ]
}
];
for(let i = 0; i < checkProvider.length; i++) {
let currentProvider = checkProvider[i];
let name = currentProvider.name;
let lengthOptions = currentProvider.length;
let prefixLengthOptions = currentProvider.prefixLength;
let prefixType = currentProvider.prefixType;
let prefixOptions = currentProvider.prefix;
for(let j = 0; j < lengthOptions.length; j++) {
let currentLength = lengthOptions[j];
if (currentLength === length) {
//Use first
for (let y = 0; y < prefixLengthOptions.length; y++) {
let currentPrefixLength = prefixLengthOptions[y];
if(currentPrefixLength === 1) {
if (first === '4') {
if (firstFour !== 4903 && firstFour !== 4905 && firstFour !== 4911 && firstFour !== 4936) {
return name;
}
}
}
if (currentPrefixLength === 2) {
if (prefixType === 'complexRange') {
return(name);
}
if (prefixType === 'simple') {
for (let i = 0; i < prefixOptions.length; i++) {
if (firstTwo === prefixOptions[i].toString()) {
return name;
}
}
}
if (prefixType === 'range') {
let min = prefixOptions[0];
let max = prefixOptions[1];
for (let i = min; i < max + 1; i++) {
if (firstTwo === i.toString()) {
return name;
}
}
}
}
}
}
}
}
}
var n = detectNetwork('6011123456789303');
console.log(n); // Discover

Converting an object with multiple arrays to a multi dimensional array

I have this format:
Data = {
"count": [ 62, 58, 10, 6 ],
"categoires": [ "a1", "a2", "a3", "a4" ]
}
I need to get get data in to the following format:
data = [
[ "a1", 62 ],
[ "a2", 58 ],
[ "a3", 10 ],
[ "a4", 6 ]
]
Can anyone help me do this?
Try using while loop
var data = {
"count": [62, 58, 10, 6],
"categoires": ["a1", "a2", "a3", "a4"]
}
var res = [], // array to push values to
i = 0, // begin at index `0`
len = data["categoires"].length; // max length
while (i < len) {
res.push([data["categoires"][i], data["count"][i]]); // push data tob `res`
++i; // increment index
}
console.log(res);
document.body.textContent = JSON.stringify(res, null, 2)
body {
white-space:pre;
}
You can loop using for and length properties:
var data = [];
for (var i = 0; i < Data.count.length; i++)
data[i] = [ Data.categoires[i], Data.count[i] ];

Categories