How can I store numbers in arrays? - javascript

I built a program that check if there are two common numbers in two different arrays, and then log those numbers. I was able to do that using a simple for loop that goes trough each element of the first array and check if there is an equal element in the second array. Each of the same element in the arrays are stored in a third array called "commonNumbers" which I logged at the end of the program.
const firstNumbers = [12, 45, 6, 78]
const secondNumbers = [6, 7, 12, 45]
let commonNumbers = []
for (let i = 0; i < firstNumbers.length; i++) {
for (let j = 0; j < secondNumbers.length; j++) {
if (firstNumbers[i] === secondNumbers[j]) {
commonNumbers += secondNumbers[j]
}
} }
console.log(commonNumbers)
The result for this example is the seguent:
12456
[Finished in 0.2s]
My question is about the result. I can see that the program actually worked and logged the same element in the arrays (12, 45, 6), but I can't figure out why "commonNumbers" stored the result in such a way that there are no spaces between the numbers.
I would like to clearly see each number.
For example if I call the first element of "commonNumbers" (of index 0):
commonNumbers[0] the result I will get is not going to be "12" as expected, but "1".
Same thing happen if I say: commonNumbers[2] the result is going to be "4", not "6".
Apparently "commonNumbers" array stored the element in a different way I was expecting. How can I solve this, using this "storing" method?

This is because +=, on your array, implicitly convert it to a string, as you can see in the example below, where a Number is summed to an Array.
console.log(typeof([] + 1));
Just use the comfortable .push (read more about push here) method of arrays in order to add the element:
const firstNumbers = [12, 45, 6, 78]
const secondNumbers = [6, 7, 12, 45]
let commonNumbers = []
for (let i = 0; i < firstNumbers.length; i++) {
for (let j = 0; j < secondNumbers.length; j++) {
if (firstNumbers[i] === secondNumbers[j]) {
commonNumbers.push(secondNumbers[j]);
}
} }
console.log(commonNumbers)
As a (final) side note, there are several other ways to accomplish your task, the cleverest you can probably go with is filter. You may also would take care of eventual duplicates, since if your input array has two identical numbers the commonsNumber result will contain both, which might be unintended.
The "definitive" clever solution that tries to also take care of duplicates and to loop the shorter array would be something like this:
// Inputs with duplicates, and longer array on second case.
const firstNumbers = [12, 45, 6, 78, 12, 12, 6, 45];
const secondNumbers = [6, 7, 12, 45, 45, 45, 12, 6, 99, 19, 5912, 9419, 1, 4, 8, 6, 52, 45];
// Performance: look for duplicates starting from the shortest array. Also, make a set to remove duplicate items.
const [shortestArray, longestArray] = firstNumbers.length < secondNumbers.length ? [firstNumbers, secondNumbers] : [secondNumbers, firstNumbers];
// Remove duplicates.
const dedupes = [...new Set(shortestArray)];
// Find commomn items using filter.
const commons = dedupes.filter(i => longestArray.indexOf(i) > -1);
console.log('commons is', commons);
Don't get me wrong, the solution is fine, just wanted to add "something" to the boilerplate, to take care of eventual additional scenarios.

const firstNumbers = [12, 45, 6, 78]
const secondNumbers = [6, 7, 12, 45]
let commonNumbers = []
for (let i = 0; i < firstNumbers.length; i++) {
for (let j = 0; j < secondNumbers.length; j++) {
if (firstNumbers[i] === secondNumbers[j]) {
commonNumbers.push(secondNumbers[j])
}
} }
The push method appends values to an array.

You seem to be looking for array.prototype.push (mdn). E.g.:
const firstNumbers = [12, 45, 6, 78]
const secondNumbers = [6, 7, 12, 45]
let commonNumbers = []
for (let i = 0; i < firstNumbers.length; i++)
for (let j = 0; j < secondNumbers.length; j++)
if (firstNumbers[i] === secondNumbers[j])
commonNumbers.push(secondNumbers[j]);
console.log(commonNumbers); // as an array
console.log(commonNumbers.join(', '));
why "commonNumbers" stored the result in such a way that there are no spaces between the numbers.
The + operator will try to cast its operands to compatible types. In this case, that is a string, where empty arrays [] are cast to empty strings '', and numbers 3 are cast to the corresponding string '3'. E.g. [] + 3 is the string '3'.
console.log([], typeof []);
console.log(3, typeof 3);
console.log([] + 3, typeof ([] + 3));

Related

Does anyone know why my for loop is stopping at 10 and not completing the rest of index in my array test?

Im trying to take an array of numbers and finding the two adjacent numbers with the highest product. So created a function that multiplies the first two indexes od the array and pushes that product to a new array. My code works for the first index positions but stops and doesn't complete the remaining indexes. What am I doing wrong. This is a code signal practice exercise.
Test: inputArray: [3, 6, -2, -5, 7, 3]
Output: [18, -12, 10]
function solution(inputArray) {
var newArray = []
for (var i = 0; i < inputArray.length; i++) {
const indexOneAndTwoProduct = inputArray[0] * inputArray[1]
newArray.push(indexOneAndTwoProduct)
inputArray.shift()
}
return newArray
}
console.log(solution([3, 6, -2, -5, 7, 3]));
It's a good practice do not modify the same array that you are iterating.
I think that something like this could work:
function solution(inputArray) {
const newArray = []
for (let i = 0; i < inputArray.length - 1; i++) {
const indexOneAndTwoProduct = inputArray[i] * inputArray[i + 1]
newArray.push(indexOneAndTwoProduct)
}
return newArray
}
console.log(solution([3, 6, -2, -5, 7, 3]))

Get data from each array of array with sequence output

i am trying to get sequence index of each array of array like I have an element of the array and that 5 arrays have multiple elements and I want to get the first index of each array then the second and so.
below is my array data
const arrData = [[1,2,4,6],[3,8,7],[12,13],[],[9,10]];
and my expected outout [1,3,12,9,2,8,13,10,4,7,6]
give me some sort of solution to fix my issue
Following might work:
const src = [[1,2,4,6],[3,8,7],[12,13],[],[9,10]],
pickByOne = arr => {
const result = [],
{length} = arr.flat()
while(result.length < length){
for(a of arr){
a.length && result.push(a.shift())
}
}
return result
}
console.log(pickByOne(src))
You can also use zip from lodash. Since the function takes a sequence of arguments and you have an array, you'll need to spread the array with ...
const _ = require("lodash");
const arrData = [[1,2,4,6],[3,8,7],[12,13],[],[9,10]];
const z = _.zip(...arrData)
This will give you the following result:
[
[ 1, 3, 12, undefined, 9 ],
[ 2, 8, 13, undefined, 10 ],
[ 4, 7, undefined, undefined, undefined ],
[ 6, undefined, undefined, undefined, undefined ]
]
You can already see it's in the order that you want. Now to clean things up. You can use flatMap in its simplest form to flatten the array.
// lodash
const fm = _.flatMap(z)
// or with Array.prototype.flat()
const fm = z.flat()
This will give you a single array.
[
1, 3, 12,
undefined, 9, 2,
8, 13, undefined,
10, 4, 7,
undefined, undefined, undefined,
6, undefined, undefined,
undefined, undefined
]
Now you just need to remove all the undefined elements by filtering (keeping) all the elements that are not undefined.
// lodash
_.filter(fm, _.negate(_.isUndefined))
and you have your final result.
[1, 3, 12, 9, 2, 8, 13, 10, 4, 7, 6]
There are many ways to solve this issue so you'll need to decide based on your particular case and balance simplicity, code legibility, efficiency, etc.
Find the longest length of the sub-array using Array.map() to get the length of all sub-arrays, and Math.max(). Use Array.from() to create an array with the length of the longest length. For each index in the created array, use Array.flatMap() to get all items from the original sub-arrays. If the item is undefined, use the Nullish coalescing operator (??) to substitute it with an empty array, which Array.flatMap() would ignore when flattening the resulting array. Flatten the output of Array.from() using Array.flat() to get a single array.
const fn = arr =>
Array.from({ length: Math.max(...arr.map(o => o.length)) }, (_, i) =>
arr.flatMap(o => o[i] ?? [])
).flat();
const arrData = [[1,2,4,6],[3,8,7],[12,13],[],[9,10]];
const result = fn(arrData);
console.log(result);
Please try my below solution may be it will fix your
let data = [[], [], [1, 2, 4, 6], [8, 9, 10], [], [12], [14, 15], []], index = 0;
data = data.filter(o => o.length != 0)
const result = [];
for (i = 0; i < data.length; i++) {
if (data[i].length > index) {
index = data[i].length
}
if (data[i].length > 0) {
for (j = 0; j < index; j++) {
if (data[j][i] != undefined) {
result.push(data[j][i]);
}
}
}
}
console.log("Result", result);
Since it's a nested array, you can loop through and check if the first element of each nested array is undefined or not. If no, you can push it into the result array. I wrote the function for your ref. Please check
const arrData = [[1, 2, 4, 6], [3, 8, 7], [12, 13], [], [9, 10]];
function sorter(arr) {
var result = [];
if (arr.length > 0) {
for (var i = 0; i < arr.length; i++) {
if (arr[i].length > 0) {
if (arr[i][0] !== undefined) {
result.push(arr[i][0]);
}
}
}
}
return result;
}
console.log(sorter(arrData));
I hope this is what you expected! Please reach me if you need clarification.
You need to keep track of the index which defines the position of the elements to get in each iteration.
Use a while loop that would terminate when there are no remaining elements in any of the arrays at a certain index.
Use .map to get a list of elements in each array at the index
Remove undefined elements in this list using .filter in case one of the arrays has no element at an index
Use .isEmpty to check if this list is empty, then, terminate
const arrData = [[1,2,4,6],[3,8,7],[12,13],[],[9,10]];
let res = [], index = 0;
while(true) {
const elementsAtIndex = _.filter(
_.map(arrData, e => e[index]),
e => e!==undefined
);
if(_.isEmpty(elementsAtIndex)) break;
res = [...res, ...elementsAtIndex];
index++;
}
console.log(...res);
<script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.17.20/lodash.min.js" integrity="sha512-90vH1Z83AJY9DmlWa8WkjkV79yfS2n2Oxhsi2dZbIv0nC4E6m5AbH8Nh156kkM7JePmqD6tcZsfad1ueoaovww==" crossorigin="anonymous"></script>
Simple one without any operator whould look like....
const ipArr = [ [1, 2, 4, 6], [8, 9, 10], [], [12], [14, 15], [] ]
let maxLength = 0
for (let i = 0; i < ipArr.length; i++) {
if (ipArr[i].length > maxLength) maxLength = ipArr[i].length
}
const opArr = []
for (let j = 0; j < maxLength; j++) {
for (let k = 0; k < ipArr.length; k++) {
if (ipArr[k][j]) opArr.push(ipArr[k][j])
}
}
console.log('opArr = ', opArr)

JavaScript: Add sum of even value elements to each odd value element in an given array; show the new array

I need to write a code that adds the sum of even value elements to each odd value element in a given array and then show the new array.
Example:
array = [2,3,4,5,6,7,8,9]
Requested sum is 20. The new generated array should look like:
array = [2, 23, 4, 25, 27, 8, 29]
What I have done so far:
let oldArray = [2, 3, 4, 5, 6, 7, 8, 9];
const sumArray = arr => arr.filter(i => !(i % 2)).reduce((a, b) => a + b);
let newArray = oldArray.map (i => i%2 == 1 + sumArray);
console.log(newArray);
Take a look at this:
let array = [2, 3, 4, 5, 6, 7, 8, 9];
console.log(array.map(x=>x%2==0?x:x+array.reduce((a,b)=> a + b*((b+1)%2) )))
It's logging an array built on the original array: if the element is even, you leave it that way. If not, you add the sum of the even numbers. How do you do this? You add the element multiplied by the rest of the division of this element added to 1 by 2.
let array = [2,3,4,5,6,7,8,9];
let newarray = [];
let sum = 0;
for(let i=0; i<array.length; i++) {
if(array[i]%2 === 0) {
sum += array[i];
}
}
for(let i=0; i<array.length; i++) {
if(array[i]%2 === 0) {
newarray.push(array[i]);
}
else {
newarray.push(array[i]+sum);
}
}

Can you sort positive integers in O(N) (linear) time using an object in JavaScript?

I need to sort an array of positive integers.
It's easy enough to do via JavaScript's sort method in O(N * log(N)):
let a = [4, 1, 3, 9, 7, 19, 11];
a.sort((a,b) => a - b);
return a;
// returns [1, 3, 4, 7, 9, 11, 19]
But, it seems like it can be done in O(N) using a JavaScript object?
Looping through the array to add an integer into an object is O(N), then grabbing the values from that object is also O(N). (Alternatively, grab the keys and convert back to numbers).
let o = {};
let a = [4, 1, 3, 9, 7, 19, 11];
a.forEach(integer => { o[integer] = integer });
return Object.values(o);
// returns [1, 3, 4, 7, 9, 11, 19]
Drop the constant and we're looking at sorting positive integers in O(N) (sacrificing additional O(N) space).
From everything I've read, this shouldn't be possible. What am I missing here?
The internal code used for setting and retrieving keys is implementation-dependent. The output (and order) is guaranteed (for all property enumeration methods, as of ES2020), but the mechanism is up to the implementer. You'd have to look at the engine source code for that.
I don't know the code that the different Javascript engines are running under the hood, but if you know of an upper bound on the number in the array, this is possible in O(n) (or, more precisely, O(n + k) where k is a constant - the upper bound) by using counting sort: create a map of the keys (similar to you're doing, but including the number of times each item appears), then iterate from 0 to the upper bound, checking to see if the number being iterated over is included in the keys. If so, push to the array:
let o = {};
let a = [4, 1, 3, 9, 7, 19, 11];
// O(n)
for (const num of a) {
if (!o[num]) {
o[num] = [];
}
o[num].push(num);
}
// O(n). This part isn't strictly necessary, but the alternative makes the code uglier
const max = Math.max(...a);
const result = [];
// O(k)
for (let i = 0; i <= max; i++) {
if (o[i]) {
// total of O(n) items pushed over the whole loop
result.push(...o[i]);
}
}
console.log(result);
If, like in your example, there are no repeated numbers, the code is significantly easier:
let o = {};
let a = [4, 1, 3, 9, 7, 19, 11];
for (const num of a) {
o[num] = true;
}
// O(n)
const max = Math.max(...a);
const result = [];
// O(k)
for (let i = 0; i <= max; i++) {
if (o[i]) {
// total of O(n) items pushed over the whole loop
result.push(i);
}
}
console.log(result);

Looping through an array and exiting when the right value is matched?

In short, is there a way to exit the loop if my condition is met in a functional way?
Let me elaborate.
Let's say I have an array:-
var arr = [4,6,2,24,16,13,88,64,28,39,66,26,9]
and I want to extract the first odd number from arr.
My initial thought was that I could just use .some and get the first element whenever my condition is met but when I went over MDN I quickly found out that it's not as simple as I thought it would be cause .some only returns boolean value.
So, my another approach was to use .filter which would filter out all the odd numbers and grab the first one but doing this will make the loop go through the entire array even though filter has already found the first odd number in the loop. This is okay for small arrays but for arrays with huge elements, it feels that this is quite unnecessary.
Am I missing something with functional technique or is this usually how functional programming goes?
Just for the reference my solution with .some and .filter are:-
var result1, result2;
//Loop ends on the right element but result wrong value
var arr = [4, 6, 2, 24, 16, 13, 88, 64, 28, 39, 66, 26, 9];
result1 = arr.some(function (i) {
return i % 2;
});
//Has right value but loop continues till the end
result2 = arr.filter(function (i) {
return i % 2;
})[0];
You can use some with a variable to store the first odd value.
Fiddle
var arr = [4, 6, 2, 24, 16, 13, 88, 64, 28, 39, 66, 26, 9];
var odd = 0;
arr.some(function(i) {
console.log(i); // To check if this loop over all the elements of array
odd = i; // Assign the value
return i % 2;
});
document.write(odd);
You can use array.prototype.find - included on that page is a polyfill for stupid browsers
usage:
result1 = arr.find(function(i){
return i%2;
});
Try using a while loop
var arr = [4, 6, 2, 24, 16, 13, 88, 64, 28, 39, 66, 26, 9];
var i = 0;
// should break if odd number found,
// `i` would be index of first odd number found in `arr`
while (arr[i] % 2 === 0 && i < arr.length) {
++i;
};
console.log(arr[i])

Categories

Resources