Sum values in 2D array based on lookup value - Javascript - javascript

I have two arrays:
const array = [
[1, 7, 'AAA'],
[2, 5, 'BBB'],
[3, 2, 'CCC'],
[4, 4, 'DDD'],
[4, 9, 'EEE'],
[4, 2, 'FFF'],
[5, 8, 'GGG'],
[6, 2, 'HHH']];
const names = [
[1, 'Joe'],
[2, 'Dave'],
[3, 'Mike'],
[4, 'Sandra'],
[5, 'Sue'],
[6, 'Mary']];
Based on the value in the first column, I want to sum the values in the array[1] and list the three-character letters. The result I'm trying to get is:
const names = [
[1, 'Joe',7,'AAA'],
[2, 'Dave',5,'BBB'],
[3, 'Mike',2,'CCC'],
[4, 'Sandra',15,'DDD, EEE, FFF'],
[5, 'Sue',8,'GGG'],
[6, 'Mary',2,'HHH']]
I'm not sure of the best approach, I'm fairly new to Javascript. What I've managed to do is get the right result when a value in array[0] isn't repeated, but I can't get a sum or list to work.
const counter = (array,value) => array.filter((v) => (v === value)).length;
const arrayCol = (array,value) => array.map(v => v[value]);
const sum = (prevVal, curVal) => prevVal + curVal;
names.forEach ((p,e) => {
array.forEach ((v,x) => (counter(arrayCol(array,0),v[0])===1) ?
(v[0]===p[0]) && names[e].push(v[1],v[2]) :
(v[0]===p[0]) && names[e].push(array.reduce(sum,0)) );
});
console.log(names);
I'm sure the answer has to do with map or filter but not sure how... any pointers appreciated. Thank you
EDIT: All three answers below (from Michael Haddad, Nina Scholz, and testing_22) work and are interesting.

You can use a combination of map and reduce, as in:
const array = [[1, 7, 'AAA'], [2, 5, 'BBB'], [3, 2, 'CCC'],[4, 4, 'DDD'], [4, 9, 'EEE'], [4, 2, 'FFF'], [5, 8, 'GGG'], [6, 2, 'HHH']];
const names = [[1, 'Joe'],[2, 'Dave'],[3, 'Mike'],[4, 'Sandra'],[5, 'Sue'],[6, 'Mary']];
const result = names.map(([id, name]) => {
let vals = [];
let sum = array.reduce((acc, [idx, number, XXX]) =>
(idx === id ? (vals.push(XXX), number) : 0) + acc, 0);
return [
id,
name,
sum,
vals.join(", ")
]
})
console.log(result)

You could collect all data for each group and then map the result in order of the names array.
const
array = [[1, 7, 'AAA'], [2, 5, 'BBB'], [3, 2, 'CCC'], [4, 4, 'DDD'], [4, 9, 'EEE'], [4, 2, 'FFF'], [5, 8, 'GGG'], [6, 2, 'HHH']],
names = [[1, 'Joe'], [2, 'Dave'], [3, 'Mike'], [4, 'Sandra'], [5, 'Sue'], [6, 'Mary']],
groups = array.reduce((r, [id, value, code]) => {
r[id] ??= [0, ''];
r[id][0] += value;
r[id][1] += (r[id][1] && ', ') + code;
return r;
}, {}),
result = names.map(a => [...a, ...groups[a[0]]]);
console.log(result);
.as-console-wrapper { max-height: 100% !important; top: 0; }

A basic approach could be:
const array = [[1, 7, 'AAA'], [2, 5, 'BBB'], [3, 2, 'CCC'], [4, 4, 'DDD'], [4, 9, 'EEE'], [4, 2, 'FFF'], [5, 8, 'GGG'], [6, 2, 'HHH']];
const names = [[1, 'Joe'], [2, 'Dave'], [3, 'Mike'], [4, 'Sandra'], [5, 'Sue'], [6, 'Mary']];
let result = [];
for (let name of names) {
let newValue = [...name, 0];
let matchingItems = array.filter(i => i[0] === name[0]);
let strings = []; // for lack of a better name...
for (let item of matchingItems) {
newValue[2] += item[1];
strings.push(item[2]);
}
newValue.push(strings.join(", "));
result.push(newValue);
}
console.log(result);
You could also implement the joining logic yourself (I actually prefer this version for readability reasons):
const array = [[1, 7, 'AAA'], [2, 5, 'BBB'], [3, 2, 'CCC'], [4, 4, 'DDD'], [4, 9, 'EEE'], [4, 2, 'FFF'], [5, 8, 'GGG'], [6, 2, 'HHH']];
const names = [[1, 'Joe'], [2, 'Dave'], [3, 'Mike'], [4, 'Sandra'], [5, 'Sue'], [6, 'Mary']];
let result = [];
for (let name of names) {
let newValue = [...name, 0, ""];
let matchingItems = array.filter(i => i[0] === name[0]);
for (let item of matchingItems) {
newValue[2] += item[1];
newValue[3] += newValue[3] === "" ? item[2] : `, ${item[2]}`;
}
result.push(newValue);
}
console.log(result);

Related

An unique arrays of numbers from an Array with JavaScript

Can anyone tell me how to solv this problem please:
I tried doing this with array.map, array.filter, array.reduce but i did not got result:
Write a function putNum(arrayOfNum: number[], num: number),
which would find all possible combinations of numbers from arrayOfNum,
whose sum is equal to number. Wherein:
arrayOfNum contains only unique positive numbers (>0)
there should not be repetitions of numbers in the combination
all combinations must be unique
#param arrayOfNum: number[]
#param num: number[]
#return Array<Array<number>>
function putNum(arrayOfNum, num) {
***// write code only inside this function***
return [[1, 2], [3]];
}
// console.log(putNum([8, 2, 3, 4, 6, 7, 1], 99)); => []
// console.log(putNum([8, 2, 3, 4, 6, 7, 1], 5)); => [[2, 3], [4, 1]]
// console.log(putNum([1, 2, 3, 4, 5, 6, 7, 8], 8)); => [[1, 3, 4], [1, 2, 5], [3, 5], [2, 6], [1, 7], [8]]
let resultnum = result.filter(e => typeof e === 'number' && e > 0); // to make a new array with nums > 0
The best approach to solve this problem in optimized way is to use hash map
let twoSum = (array, sum) => {
let hashMap = {},
results = []
for (let i = 0; i < array.length; i++){
if (hashMap[array[i]]){
results.push([hashMap[array[i]], array[i]])
}else{
hashMap[sum - array[i]] = array[i];
}
}
return results;
}
console.log(twoSum([10,20,40,50,60,70,30],50));
Output:
[ [ 10, 40 ], [ 20, 30 ] ]

To get a truthy condition(array) from a nested array, for now the function returns boolean value true

The checkWin function returns true when an array which are index numbers have a speicified symbol on another Array's indexes. How to retrieve the "cond"(array) which results in true from the nested winConditions array ?
Symbols get populated using the click event listener.
The expected result should be, if .some(cond) becomes true then return that cond for eg. if symbol "X" is present on [0, 1, 2] then return this array
let testArray = Array(9).fill("")
const winConditions = [
[0, 1, 2],
[3, 4, 5],
[6, 7, 8],
[0, 3, 6],
[1, 4, 7],
[2, 5, 8],
[0, 4, 8],
[2, 4, 6],
];
let xValue = "X";
let oValue = "O";
function checkWin(value, array) {
return winConditions.some((cond) =>
cond.every((index) => array[index] == value));
}
console.log(checkWin(xValue, testArray));
console.log(checkWin(oValue, testArray));
You can use .find() instead of .some(), this will return the first array that the .every() callback returns true for. You can use this array to determine if there was a win or not for a particular player:
const testArray = Array(9).fill("");
testArray[3] = testArray[4] = testArray[5] = "O"; // test winning position
const winConditions = [
[0, 1, 2],
[3, 4, 5],
[6, 7, 8],
[0, 3, 6],
[1, 4, 7],
[2, 5, 8],
[0, 4, 8],
[2, 4, 6],
];
const xValue = "X";
const oValue = "O";
function getWinPos(value, array) {
return winConditions.find((cond) =>
cond.every((index) => array[index] == value)
);
}
const xWinPos = getWinPos(xValue, testArray);
const oWinPos = getWinPos(oValue, testArray);
if(xWinPos) { // found a winning position row/col/diag for "X"
console.log(xWinPos);
} else if(oWinPos) { // found a winning row/col/diag for "O"
console.log(oWinPos);
}

Shift entire column in multidimensional array using only javascript or ES6

I have a multidimensional array like below and I want to shift column positions using javascript or ES6 with no jquery or any other plugins.
Eg: Initial array will look like this.
1|2|3|4
2|2|6|4
4|2|3|4
9|2|7|4
How can I shift the 4th column to 1st position so that it will look like this?
4|1|2|3
4|2|2|6
4|4|2|3
4|9|2|7
Could someone can help with logic to shift any columns like this?
You could assing a mapped outer array with new items by slicing the inner arrays with a given index.
For getting the original sort, you could shiftby the delta of length and index.
const shift = (array, index) => array.map(a => [...a.slice(index), ...a.slice(0, index)]);
var array = [[1, 2, 3, 4], [2, 2, 6, 4], [4, 2, 3, 4], [9, 2, 7, 4]],
index = 3;
array = shift(array, index);
console.log(array.map(a => a.join(' ')));
array = shift(array, array[0].length - index);
console.log(array.map(a => a.join(' ')));
.as-console-wrapper { max-height: 100% !important; top: 0; }
You can use array.map to re-arrange the values:
function rearrange(rows, pos) {
return rows.map(function(cols) {
return pos.map(function(i) {
return cols[i];
});
});
}
var old_arr;
var new_arr;
old_arr = [
[1, 2, 3, 4],
[2, 2, 6, 4],
[4, 2, 3, 4],
[9, 2, 7, 4]
];
new_arr = rearrange(old_arr, [3, 0, 1, 2]);
console.log(new_arr);
old_arr = [
[1, 2, 3, 4],
[2, 2, 6, 4],
[4, 2, 3, 4],
[9, 2, 7, 4]
];
new_arr = rearrange(old_arr, [3, 2, 1, 0]);
console.log(new_arr);

Symmetric Difference javascript

I am trying to solve this freecodecamp algorithm question where I had to collect the difference of two or more arrays. I used map to get the difference of array but the problem is I only get two elements;
function sym(args) {
args = [].slice.call(arguments);
var newArr = args.map(function(el, index, arr){
console.log(arr.indexOf(arr[index]));
if(arr.indexOf(arr[index] === -1 )){
// console.log(arr[index]);
return args.push(arr[index]);
}
});
return newArr; // my newArr returns [3, 4] instead of [3,4,5]
}
console.log(sym([1, 2, 3], [5, 2, 1, 4]));
//sym([1, 2, 3], [5, 2, 1, 4]) should return [3, 4, 5]
//sym([3, 3, 3, 2, 5], [2, 1, 5, 7], [3, 4, 6, 6], [1, 2, 3], [5, 3, 9, 8], [1]) should return [1, 2, 4, 5, 6, 7, 8, 9]
I think we could do also this way since we want them to be ordered at the end.
For more detail about the original problem please consult this link: FreecodeCamp Link: Symmetric Difference
const sym = (...args) => {
// Merge all the different arrays and remove duplicate elements it means elements that are present both on two related arrays
let tab = args.reduce((a, b) => [
...a.filter(i => !b.includes(i)),
...b.filter(j => !a.includes(j))
], []);
// Then remove the rest of duplicated values and sort the obtained array
return Array.from(new Set(tab)).sort((a, b) => a - b);
}
console.log(sym([1, 2, 3, 3], [5, 2, 1, 4])); // [3, 4, 5]
console.log(sym([1, 1, 2, 5], [2, 2, 3, 5], [3, 4, 5, 5])); // [1, 4, 5]
console.log(sym([3, 3, 3, 2, 5], [2, 1, 5, 7], [3, 4, 6, 6], [1, 2, 3], [5, 3, 9, 8], [1])); // [1, 2, 4, 5, 6, 7, 8, 9]
The Set data structure is used here to remove duplicated values thanks to its characteristics.
Well your function is a little more complex than only selecting the unique values, cause you want to filter them out... and also accept multiple arrays. This should work.
var sym = (...arrays)=>{
//Concat Items
const allItems = arrays.reduce((a,c)=>a.concat(c), []);
// Identify repeated items
const repeatedItems = allItems.filter((v,i,a)=>a.indexOf(v) !== i);
// Filter repeated items out
const diff = allItems.filter(item=>repeatedItems.indexOf(item) < 0);
console.log(diff);
};
sym([1, 2, 3], [5, 2, 1, 4]); // [3,5,4]
I don't think your approach will work; you're supposed to create an array with elementos from both arrays, so a single .map won't do the job. Filtering through both arrays should work, although it will probably leave enough room for optimization.
my newArr returns [3, 4] instead of [3,4,5]
You are using map which will only return one value per iteration (which is why you are getting only 2 values) and in your case you are checking if the index is found or not (not the item)
You need to concatenate all the arrays and then remove those which are repeated
Concatenate
var newArr = args.reduce( ( a, c ) => a.concat( c ) , []);
Create a map by number of occurrences
var map = newArr.reduce( (a,c) => ( a[c] = (a[c] || 0) + 1, a ) , {});
Iterate and filter through those keys whose value is 1
var output = Object.keys( map ).filter( s => map[s] === 1 ).map( Number );
Demo
function sym(args)
{
args = [].slice.call(arguments);
var newArr = args.reduce( ( a, c ) => a.concat( c ) , []);
var map = newArr.reduce( (a,c) => ( a[c] = (a[c] || 0) + 1, a ) , {});
return Object.keys( map ).filter( s => map[s] === 1 ).map( Number );
}
console.log(sym([1, 2, 3], [5, 2, 1, 4]));
You could take an Object for counting the items and return only the items which have a count.
function sym(array) {
return array.reduce((a, b) => {
var count = {};
a.forEach(v => count[v] = (count[v] || 0) + 1);
b.forEach(v => count[v] = (count[v] || 0) - 1);
return Object.keys(count).map(Number).filter(k => count[k]);
});
}
console.log(sym([[3, 3, 3, 2, 5], [2, 1, 5, 7], [3, 4, 6, 6], [1, 2, 3], [5, 3, 9, 8], [1]]));

Javascript - matching first value from array search with value from other array

So let's say we have two arrays
const arr1 = [1, 2, 3, 4, 5];
const arr2 = [6, 7, 8, 9, 10, 4, 5,];
I want to return just the first matching value without doing two for loops. So not by taking first value from arr1 look for it in arr2 then second value ect.
I this case I would need to return 4.
Working in React/Redux enviroment without jQuery possible.
const arr1 = [1, 2, 3, 4, 5];
const arr2 = [6, 7, 8, 9, 10, 4, 5,];
arr1.find((x) => arr2.indexOf(x) >=0);
That'll grab the first match
You can use find() with includes() method.
const arr1 = [1, 2, 3, 4, 5];
const arr2 = [6, 7, 8, 9, 10, 4, 5,];
var r = arr1.find(e => arr2.includes(e));
console.log(r)
Ecmascript5 solution (with Array.some() function):
var arr1 = [1, 2, 3, 4, 5],
arr2 = [6, 7, 8, 9, 10, 4, 5,],
result;
arr2.some(function(n){ return arr1.indexOf(n) !== -1 && (result = n) })
console.log(result);
You could use the power of Set.
const
arr1 = [1, 2, 3, 4, 5],
arr2 = [6, 7, 8, 9, 10, 4, 5],
result = arr2.find((s => a => s.has(a))(new Set(arr1)));
console.log(result);

Categories

Resources