Related
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 ] ]
Could I have some guidance on how to extract multiple columns from a two-dimensional array like the below using JavaScript?
Array = [
[1, 2, 3, 4],
[5, 6, 7, 8],
[9,10,11,12],
];
the simple methods I've seen so far using forEach or map will allow extraction of ONE column at a time, is there a way to nest it somehow to extract whichever column index one desire?
Let's say the desire output column is 1,2 and 4.
Output = [
[1, 2, 4],
[5, 6, 8],
[9,10,12],
];
EDIT:
Another problem I need to resolve is how to remove a row if it's Array[i][1]=0 or empty.
Let say we have extra array elements...
Array = [
[1, 2, 3, 4],
[5, 6, 7, 8],
[9,10,11,12],
[13,0,15,16],
[17, ,19,20],
[21,22,23,24],
];
The desired output is now...
Output = [
[1, 2, 4],
[5, 6, 8],
[9,10,12],
[21,22,24],
];
You can .map() each row in arr to a new array which you can obtain by using an inner .map() on an array of columns/indexes which you wish to obtain. The inner map will map each index to its associated value from the row, giving you the values at each column for each row.
See example below:
const arr = [
[1, 2, 3, 4],
[5, 6, 7, 8],
[9,10,11,12],
];
const cols = [1, 2, 4];
const res = arr.map(r => cols.map(i => r[i-1]));
console.log(res);
Further details:
As you mentioned the first map exposes each inner array inside of arr to the inner mapping function:
cols.map(i => r[i-1])
This mapping function will loop through the indexes defined inside of cols and transform them into a new value. For example, say you're r is the second array:
[5, 6, 7, 8]
Performing cols.map(...) will loop over each element (denoted by i in the callback function) in [1, 2, 4]. For each element, we "transform" it into a new element:
i = 1
r = [5, 6, 7, 8]
new value: r[1-1] = 5
Next iteration we look at the next value in cols:
i = 2
r = [5, 6, 7, 8]
new value: r[2-1] = 6
Lastly, we look at the final value in cols:
i = 4
r = [5, 6, 7, 8]
new value: r[4-1] = 8
So the mapping function produces a new array which transforms the values from cols [1, 2, 4], into the values at those indexes in the current row to be [5, 6, 8]. This occurs for each inner array / row, producing the final result.
EDIT
As per your edit, you can apply the same logic from above to get your arrays with only the columns you desire. Once you have done that you can use .filter() to keep only the rows which have a truthy value in the second column. Keeping all the arrays with truthy values in the second column will remove the arrays with non-truthy values in the second column (falsy values) from your resulting array. 0 and undefined are both flasy values, so they are not kept.
See example below:
const arr = [
[1, 2, 3, 4],
[5, 6, 7, 8],
[9,10,11,12],
[13,0,15,16],
[17, ,19,20],
[21,22,23,24],
]
const cols = [1, 2, 4];
const col = 2;
const res = arr.filter(r => r[col-1]).map(r => cols.map(i => r[i-1]));
console.log(res);
If you have multiple columns you want to ignore, you can use .every() to ensure each (ie: every) column contains a truthy value. If they all do, then .every() will return true, keeping the column, otherwise, it will return false, removing the column:
const arr = [
[1, 2, 3, 4],
[5, 6, 7, 8],
[9,10,11,12],
[13,0,15,16],
[ ,17,19,20],
[21,22,23,24],
]
const cols = [1, 2, 4];
const col = [1, 2];
const res = arr.filter(r => col.every(c => r[c-1])).map(r => cols.map(i => r[i-1]));
console.log(res);
You can approach it the below given way. The solution is using the index parameter available in filter method .
Array.filter(currElem,index,array)
Since array is 0-indexed ,so I created the array with index you want in the data as [0,1,3] . You need to pass the data array and index array to the function .
var array = [
[1, 2, 3, 4],
[5, 6, 7, 8],
[9,10,11,12],
];
var arrIndex = [0,1,3];
function extractData(arr,indexArr) {
return arr.map(obj => {
return obj.filter((ob,index) => {
if(indexArr.includes(index)){return ob}
})
})
}
console.log(extractData(array,arrIndex));
I have 10 arrays of data that look like this:
var arr = [1,2,3,4,5,6,7,8,9,10]
var arr2=['hello','hello1','hello2','hello3','hello4','hello5','hello6','hello7','hello8','hello9']
...8 More Arrays
Each array will have exactly the same number of elements every time. I wanted to know the best way to generate an array of objects that look like this that combines the various arrays:
overallarray = [{
arr1 = 1,
arr2 = 'hello'
...
},
{
arr1 = 2,
arr2 = 'hello1'
...
}]
I recognize that I can use a large number of for loops but am looking for a more optimized solution that someone might have.
This is where Array.map() will be your friend. You can iterate through any of the arrays (since they have the same number of elements) and then access each element by index to get the corresponding value for each array in your dataset, like so:
var arr = [0,1,2,3,4,5,6,7,8,9]
var arr2=['hello','hello1','hello2','hello3','hello4','hello5','hello6','hello7','hello8','hello9'];
var arr3=['foo','foo1','foo2','foo3','foo4','foo5','foo6','foo7','foo8','foo9'];
let mapped = arr.map((elem, index) => {
return {
arr1: arr[index],
arr2: arr2[index],
arr3: arr3[index]
}
});
console.log(mapped);
Edit: If you wanted to access them generically, you can add all of your arrays to one dictionary and iterate over the key/value pairs, like so:
var arr = [0,1,2,3,4,5,6,7,8,9]
var arr2=['hello','hello1','hello2','hello3','hello4','hello5','hello6','hello7','hello8','hello9'];
var arr3=['foo','foo1','foo2','foo3','foo4','foo5','foo6','foo7','foo8','foo9'];
// combine all arrays into single dataset
let data = {arr, arr2, arr3};
let mapped = arr.map((elem, index) => {
// iterate over the key/value pairs of the dataset, use the key to generate the
// result object key, use the value to grab the item at the current index of the
// corresponding array
return Object.entries(data).reduce((res, [key, value]) => {
res[key] = value[index];
return res;
}, {});
});
console.log(mapped);
Assuming arr1,arr2 are not desired names of resulting object properties, if you need something
that scales nicely for arbitrary number of data arrays
assigns arbitrary key names (not necessarily corresponding to array variable names, or, worse, property name(s) that can't be valid variable name are needed)
works muuuch faster than accepted solution ;)
You may do the following:
const arr1 = [1,2,3,4,5,6,7,8,9,10],
arr2=['hello','hello1','hello2','hello3','hello4','hello5','hello6','hello7','hello8','hello9'],
keyNames = ['id', 'greeting'],
group = (...arrays) => (keys) =>
arrays.reduce((res, arr, idx) =>
(arr.forEach((e,i) => res[i][keys[idx]] = e), res),
Array.from({length:arrays[0].length}, () => ({}))
)
console.log(group(arr1,arr2)(keyNames))
.as-console-wrapper {min-height:100%;}
Just iterate all arrays with 1 loop counter:
var dataArrayOne = [1, 2, 3, 4 ];
var dataArrayTwo = ["hello", "hello1", "hello2", "hello3" ];
...
var resultArray = [];
for (var i = 0; i < 4; i++)
{
var combined = {
arr1: dataArrayOne[I],
arr2: dataArrayTwo[i]
...
};
resultArray.push(combined);
}
You can get from this:
[ [1, 2, 3]
, [4, 5, 6]
, [7, 8, 9]
]
to this:
[ [1, 4, 7]
, [2, 5, 8]
, [3, 6, 9]
]
with this function:
const combine =
(...arrs) =>
[ arrs.map(xs => xs[0])
, ... ( arrs.every(xs => xs.length === 1)
? []
: combine(...arrs.map(xs => xs.slice(1)))
)
];
combine
( [1, 2, 3]
, [4, 5, 6]
, [7, 8, 9]
);
Then from this:
[ [1, 4, 7]
, [2, 5, 8]
, [3, 6, 9]
]
to this:
[ {arr1: 1, arr2: 4, arr3: 7}
, {arr1: 2, arr2: 5, arr3: 8}
, {arr1: 3, arr2: 6, arr3: 9}
]
with this function:
const to_obj =
(...arrs) =>
arrs.map(arr =>
Object.fromEntries(
arr.map((x, i) => [`arr${i+1}`, x])));
to_obj
( [1, 4, 7]
, [2, 5, 8]
, [3, 6, 9]
)
Hopefully connecting the two functions together is straightforward.
A note about performance
With exactly 10 arrays of 10 elements each, it is unlikely that you can tell whether a particular solution performs better than another. You should probably go for the solution that feels right in terms of readability or maintenance.
By these criteria you should probably exclude mine; just wanted to share a different approach.
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]]));
I have an adjacency list like below:
const list = [
[1, 6, 8],
[0, 4, 6, 9],
[4, 6],
[4, 5, 8],
// ...
];
I need to create a set of links for an undirected graph without duplicates (example bellow).
Such links as [0,1] and [1,0] are considered duplicates.
const links = [
[ 0, 1 ], // duplicates
[ 0, 6 ],
[ 0, 8 ],
[ 1, 0 ], // duplicates
[ 1, 4 ],
// ...
]
Right now I do it this way:
const links = new Set;
const skip = [];
list.forEach( (v, i) => {
v.forEach( j => {
if (skip.indexOf(j) === -1) {
links.add([i, j]);
}
})
skip.push(i);
})
I am wondering if there is a better pattern to solve this kind of task on massive arrays.
You could sort your link tuple values, skip the check skip.indexOf(j) and let Set take care of the duplicates.
You could take a stringed array as value for the for the set, because an array with only sorted value is checking with strict mode in the set.
A primitive data type, like string works best.
var list = [[1, 6, 8], [0, 4, 6, 9], [4, 6], [4, 5, 8]],
links = new Set;
list.forEach((v, i) => v.forEach(j => links.add([Math.min(i, j), Math.max(i, j)].join())));
console.log([...links]);
.as-console-wrapper { max-height: 100% !important; top: 0; }
You can use one object to store value: index that has already been used and then check that object before adding to array.
const list = [[1, 6, 8],[0, 4, 6, 9],[4, 6],[4, 5, 8],];
var o = {},r = []
list.forEach(function(e, i) {
e.forEach(function(a) {
if (o[i] != a) {
r.push([i, a])
o[a] = i
}
})
})
console.log(JSON.stringify(r))
With ES6 arrow functions you can write the same like this.
const list = [[1, 6, 8], [0, 4, 6, 9], [4, 6], [4, 5, 8],];
var o = {}, r = []
list.forEach((e, i) => e.forEach(a => o[i] != a ? (r.push([i, a]), o[a] = i) : null))
console.log(JSON.stringify(r))