Related
I have the following array:
let numbers = [10, 20, 20, 10, 10, 30, 50, 10, 20];
I create a new array without the duplicate values:
let counter = [...new Set(array)];
//Output: [ 10, 20, 30, 50 ]
I want to instantiate the counter array as a 2D/nested array so that it looks like this:
//counter output: [[10,4][20, 3][30, 1][50,1]]
What's the best way to do this? The numbers array could have various elements and therefore the number of elements in the counter array could vary.
This answer is for the original question (how to create an array of [[10, 0],[20, 0],[30, 0],[50, 0]] from the Set):
Instead of spreading the Set, use Array.from() to create an array of pairs:
const numbers = [10, 20, 20, 10, 10, 30, 50, 10, 20];
const counter = Array.from(new Set(numbers), v => [v, 0]);
console.log(counter);
Assuming you actually want that second sub-array index to represent the number of occurrences of each number (ed: confirmed now), you can collect the counts into a Map and then convert that to an array
let numbers = [10, 20, 20, 10, 10, 30, 50, 10, 20];
const counter = [...numbers.reduce((map, n) =>
map.set(n, (map.get(n) ?? 0) + 1), new Map())]
console.info(JSON.stringify(counter)) // stringifying so it's all on one line
The array conversion works since Map supports the common entries format of
[ [ key, value ], [ key, value ], ... ]
and using spread syntax implicitly converts it to an entries array.
One way is take the ideas you have already used and map across those values returning new arrays with the value and an additional zero.
let numbers = [...new Set([10, 20, 20, 10, 10, 30, 50, 10, 20])].map(value=>[value,0]);
You can convert your original array into an object (hash map) to keep track of the count. And then convert it into to Object.entries() array.
const numbers = [10, 20, 20, 10, 10, 30, 50, 10, 20];
let obj = {};
numbers.forEach(n => {
obj[n] = obj[n] || 0;
obj[n]++;
});
const counter = Object.entries(obj).map(e => [+e[0], e[1]]);
console.log(counter);
I have this nested array
let thirarray = [
[2, 3, 4],
[5, 6, 7, 8],
[9, 10],
];
and what I'm trying to do is add the first element of each array so basically add 2+5+9= 16
I know I can access each element like this
//this is how i can access the first element of each array
console.log(thirarray[0][0]);
console.log(thirarray[1][0]);
console.log(thirarray[2][0]);
I know I can access with a nested loop all the elements like this
let suminsidearrays = 0;
for (i = 0; i < thirarray.length; i++) {
for (let j = 0; j < thirarray[i].length; j++) {
console.log(thirarray[i][j]);
suminsidearrays += thirarray[i][j];
console.log(suminsidearrays);
}
}
So my question is how can add the first element of each array?
simplest way to do it
let thirarray = [[2, 3, 4],[5, 6, 7, 8],[9, 10]];
var res=0
thirarray.forEach(a=>res+=a[0])
console.log(res)
This will sum the first element in each array inside the main array.
const array = [[2, 3, 4],[5, 6, 7, 8],[9, 10]]
let sum = array.reduce((a,c)=>a+c[0],0)
console.log(sum)
Update for new pattern requirement in the comment.
const array = [[2, 3, 4],[5, 6, 7, 8],[9, 10, 11]]
let i = 0, sum = array.reduce((a,c)=>a+c[i++],0)
console.log(sum)
I just want to add that I was able to solve it using what I learned from #holydragon.
So this is what I did
let fourthrarray = [
[20, 30, 40],
[50, 60, 70, 80],
[90, 100, 110, 120, 130],
];
let nextindexposition = 0;
let nextto = 0;
let sumeelsegundo = 0;
for (let i = 0; i < fourthrarray.length; i++) {
//this will allow me to see the 1st index position from each array
//i should expect to see 20,50,90
sumeelsegundo = fourthrarray[i][0];
//this will add the first index position of each array expected output will be 160
sumeelsegundo += fourthrarray[i][0];
console.log(sumeelsegundo);
//in order to add the next index position from each array i used two variable
//one that will store the result and the other one that will increase the index
//position by one on every iteration. this one will allow me to see the elements
//that will be added. expected elements will be 20,60,110
nextto = fourthrarray[i][nextindexposition++];
//this will be adding the elements expected output expected output 190
nextto += fourthrarray[i][nextindexposition++];
console.log(nextto);
}
Just to clarify something this solution works for adding numbers, If I wanted to multiply I just had to change the starting value on the variable nextto from 0 to 1.
Today i'm facing a really weird problem.
I'm actually trying to delete numbers below a certain number in an array.
I have this array [1, 7, 2, 3, 90, 4, 70, 20] and I only want the numbers greater than 20 !
So I should have that in output : [90, 70]
But Instead I have this array : [7, 3, 90, 70, 20] ???
Here is my code :
function superior() {
var arr = [1, 7, 2, 3, 90, 4, 70, 20]
for (var i = 0; i < arr.length; i++) {
if (arr[i] < 20) {
arr.splice(arr.indexOf(arr[i]), 1);
} else {
break;
}
}
return arr;
}
console.log(superior());
Mutating an array while you're looping through it is always going to be tricky. If you shrink the size of the array, but don't change i, then you're can end up interacting with the wrong element of the array the next time through the loop. Also, using break will stop the loop from running entirely, and so skip the rest of the array. You may have meant to use continue, but since you're on the last line of the loop anyway, continue isn't needed.
Rather than trying to change the array and loop through it at the same time, i'd recommend creating a new array. Then you can loop through the old one unhindered:
const arr = [1, 7, 2, 3, 90, 4, 70, 20]
const newArr = []
for (const i = 0; i < arr.length; i++) {
if (arr[i] >= 20) {
newArr.push(arr[i]);
}
}
console.log(newArr)
Filtering an array like this is a very common thing to do, so there are built in tools to do it for you. Every array has a .filter method. You pass into it a function describing what elements you want to keep, and it will produce the new array for you:
const arr = [1, 7, 2, 3, 90, 4, 70, 20]
const newArr = arr.filter(element => element >= 20);
console.log(newArr)
You can filter them out according to a condition.
And replace your existing array with the filtered one. Or if you don't want to replace it, use another variable and assign the filtered value to that variable.
var newArray = array.filter(item => item > 20)
Check .filter()
var array = [1, 7, 2, 3, 90, 4, 70, 20];
array = array.filter(item => item > 20)
console.log(array)
You can use Array.filter()
var arr = [1, 7, 2, 3, 90, 4, 70, 20]
var filteredArr = arr.filter(item => item > 20);
console.log(filteredArr);
You could iterate from the end and omit indexOf, because you have already the index i.
This appoach loops from the end and after splicing, the remaining lower indices remains.
function superior() {
var array = [1, 7, 2, 3, 90, 4, 70, 20],
i = array.length;
while (i--) if (array[i] < 20) array.splice(i, 1);
return array;
}
console.log(superior());
Use temporary array to push new values.
function superior() {
var arr = [1, 7, 2, 3, 90, 4, 70, 20];
temp_arr = [];
for (var i = 0; i < arr.length; i++) {
if (arr[i] > 20) {
temp_arr.push(arr[i]);
}
}
return temp_arr;
}
console.log(superior());
I need to find the union of three arrays that get passed to the function union.
It took me about 50lines to code to get the expected result. Apparently, the following code works but now I wonder what are the best ways (either in a functional and in a non-functional fashion) to do the same job.
function union(...arrays) {
var array1 = arguments[0];
var array2 = arguments[1];
var array3 = arguments[2];
var unique = [];
var intersaction = [];
// find the unique values
for(let i = 0; i < array1.length; i++) {
if( (array2.includes(array1[i]) == false) && (array3.includes(array1[i])) == false ) {
unique.push(array1[i]);
}
}
for(let i = 0; i < array2.length; i++) {
if( (array1.includes(array2[i]) == false) && (array3.includes(array2[i])) == false ) {
unique.push(array2[i]);
}
}
for(let i = 0; i < array3.length; i++) {
if( (array1.includes(array3[i]) == false) && (array2.includes(array3[i])) == false ) {
unique.push(array3[i]);
}
}
// find the intersection
for(let j = 0; j < array1.length; j++) {
if(array2.includes(array1[j]) || array3.includes(array1[j]) ) {
if (intersaction.indexOf(array1[j]) == -1) {
intersaction.push(array1[j]);
}
}
}
for(let j = 0; j < array2.length; j++) {
if(array1.includes(array2[j]) || array3.includes(array2[j]) ) {
if (intersaction.indexOf(array2[j]) == -1) {
intersaction.push(array2[j]);
}
}
}
for(let j = 0; j < array3.length; j++) {
if(array1.includes(array3[j]) || array2.includes(array3[j]) ) {
if (intersaction.indexOf(array3[j]) == -1) {
intersaction.push(array3[j]);
}
}
}
return union = [...intersaction, ...unique];
}
console.log(union([5, 10, 15], [15, 88, 1, 5, 7], [100, 15, 10, 1, 5]));
// should log: [5, 10, 15, 88, 1, 7, 100]
Just another solution keeping the original function signature provided by the OP:
function union(...arrays) {
return Array.from(new Set([...arrays].flat()));
}
console.log(union([5, 10, 15], [15, 88, 1, 5, 7], [100, 15, 10, 1, 5]));
Or, even shorter (but less read friendly):
return [...(new Set([...arrays].flat()))];
Explanation:
Array.from takes an Iterable as an argument, this will create a new array from the original one.
[...arrays] spreads the arrays (argument) into a new, single, one (So it becomes an array of arrays) -> [5, 10, 15], [15, 88, 1, 5, 7], [100, 15, 10, 1, 5] becomes: [[5, 10, 15], [15, 88, 1, 5, 7], [100, 15, 10, 1, 5]]
.flat flattens the array, making that an array of values rather than ar array of arrays of values -> https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/flat -> [[5, 10, 15], [15, 88, 1, 5, 7], [100, 15, 10, 1, 5]] becomes [5, 10, 15, 15, 88, 1, 5, 7, 100, 15, 10, 1, 5]
new Set removes duplicates from the array and returns an Iterable https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Set. -> [5, 10, 15, 15, 88, 1, 5, 7, 100, 15, 10, 1, 5] becomes a Set instance (an Iterable) without the duplicates. Array.from then converts the Set (Iterable) to a regular array. Further infos here: How to convert Set to Array?
BEWARE: Array.flat is currently an experimental feature (https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/flat). Solution without using flat below:
function union(...arrays) {
return Array.from(new Set([].concat.apply([],[...arrays])));
}
console.log(union([5, 10, 15], [15, 88, 1, 5, 7], [100, 15, 10, 1, 5]));
Explanation (only differences from above):
Instead of .flat, we apply to Array.concat our original array, so that it will flatten it passing a new array as its this and providing our array as the argument: [].concat.apply([],[...arrays])
Snippet: http://jsfiddle.net/briosheje/y03osape/2/
Snippet without .flat: http://jsfiddle.net/briosheje/y03osape/4/
use set that's very simple,
The Set object lets you store unique values of any type, whether
primitive values or object
var a= [5, 10, 15];
var b=[15, 88, 1, 5, 7];
var c=[100, 15, 10, 1, 5];
var result= [...new Set([...a, ...b,...c])];
console.log(result);
I tried to copy your approach of looping over arrays but in a slightly more efficient manner, using only ES5 safe functions. I'm sure the other answers are more efficient if you can use the features they do.
var a = [1, 2, 3];
var b = [1, 2, 4, 5];
var c = [2, 7, 9];
// takes an array of arrays
function getUnique(input) {
var unique = [];
// loop over each array
input.forEach(function(item) {
// loop over each value
item.forEach(function(value) {
// if it's not already in the unique array,
if (unique.indexOf(value) == -1) {
// add it
unique.push(value);
}
});
});
return unique;
}
// takes an array of arrays
function getIntersection(input) {
// assume all elements in first array are common
var intersection = input.shift();
var remove = [];
// loop over items in first array and attempt to
// disprove commonality
intersection.forEach(function(value) {
// loop over subsequent arrays
for (var i = 0; i < input.length; i++) {
var item = input[i];
// if these arrays don't contain the value,
// then it isn't an intersection
if (item.indexOf(value) == -1) {
// add it to an array to be removed
remove.push(value);
// exit this loop
break;
}
}
});
// remove values determined not to be intersections
remove.forEach(function(value) {
intersection.splice(intersection.indexOf(value), 1);
})
return intersection;
}
var test = getUnique([a, b, c]);
console.log(test);
var test2 = getIntersection([a, b, c]);
console.log(test2);
Based on custom forEach and Reduce from previously in the exercise at http://csbin.io/callbacks
function forEach(array, callback) {
for(i = 0; i < array.length; i++){
callback(array[i])
}
}
function reduce(array, callback, initialValue) {
for(let i of array){
initialValue = callback(initialValue, i)
}
return initialValue
}
function union(...arrays) {
return reduce(arrays, (seen, next) => {
forEach(next, (element) => {
if(!seen.includes(element)) seen.push(element);
})
return seen
}, [])
}
Note if you use the in-built reduce function you can remove the empty inital array requirement.
If I have an array with a set of numbers, and want to remove certain ones with the .filter method, I understand how to do this in when i need to remove a single item (or if i can use a mathematical expression), but can't get it to work with multiple items either purely by their value or position in the array.
In the following code I would like the new array selection to return the numbers 10, 12, 15
Also, I do need to do this with the filter() method only.
JS
let random = [4, 10, 12, 15, 30];
let selection = random.filter(function(num){
return num === [10, 12, 30];
});
You can use includes:
let random = [4, 10, 12, 15, 30, 10, 10, 12, 5];
let selection = random.filter(function(num){
var good = [10, 12, 30]
return good.includes(num);
});
console.log(selection)
Of if you prefer the terseness of arrow function:
let random = [4, 10, 12, 15, 30, 10, 10, 12, 5];
let selection = random.filter(num => [10, 12, 30].includes(num))
console.log(selection)
Forgive me if I do not understand it correctly, but if what you're looking for is to filter an array by the item's index, you can use the second parameter passed to the filter method's callback, which is the index.
let random = [4, 10, 12, 15, 30];
let selection = random.filter(function(num, index){
return index > 0 && index < 4;
});
console.log(selection);
You do need a condition that will return true or false when using filter, so the simplest way to do this with the filter method would be:
let random = [4, 10, 12, 15, 30];
let selection = random.filter(function(num){
if (num > 4 && num < 16) {return true};
});
The other way to do it would be filtering by position in the array and that would be better achieved with other array methods.
If I understand your question you want a function that takes a an array, checks if the elements are in your larger array and if they are there, removes them.
Filter might not be your best choice here because it doesn't alter the original array, it only makes a new array. Try using splice.
let random = [4, 10, 12, 15, 30];
function remove(array) {
for (var i = 0; i < array.length; i++) {
if(random.includes(array[i])){
random.splice(random.indexOf(array[i]), 1)
}
}
}
remove([10, 12, 30]);
console.log(random); // [4, 15]
I am assuming you want to remove because if you already know which elements you want why filter them out? why not just pass them into your function as a new array? filter will create a new array anyways.
But if you would like to remove elements from your first array the answer above might help.