Sorting using two arrays - javascript

There are two arrays:
The first one contain numbers, and the second one contains "weight" of the first array values.
It works like this:
arr1 = [56,65,100,89,180,90];
"Weight" of the numbers are calculated in this way:
56 = 5+6 = 11;
65 = 6+5 = 11;
100 = 1+0+0 = 1; and so on..
So, arr2 = [11,11,1,17,9,9];
My question is how can I sort the values of the arr1 according to values of arr2?
I tried to modify simple bubble sort for this problem, but nothing changed.
function bubble(arr1, arr2) {
var len = arr1.length;
for (var i = 0; i < len; i++) {
for (var j = 0; j < len - i - 1; j++) {
if (arr2[j] > arr2[j + 1]) {
var temp = arr1[j];
arr1[j] = arr1[j + 1];
arr1[j + 1] = temp;
}
}
}
return arr1;
}
arr1 = [56, 65, 100, 89, 180, 90];
arr2 = [11, 11, 1, 17, 9, 9];
console.log(bubble(arr1, arr2));
I expect the output of the bubble function to be [100,180,90,56,65,89].
This is why:
FirstArray - [56,65,100,89,180,90] - arr1
"Weight of the values"[11,11, 1, 17, 9, 9 ] - arr2
Output [100,180,90,56,65,89]
[1, 9, 9 ,11,11,17]

You can just calculate the weight on the fly while sorting:
const arr = [56,65,100,89,180,90];
arr.sort( (a,b) =>
(a + '').split( '' ).reduce( (sum,x) => sum + +x, 0 ) -
(b + '').split( '' ).reduce( (sum,x) => sum + +x, 0 )
);
console.log( arr );

To achieve expected result, use below option of sorrting arr1 with logic mentioned in question
Sort arr1 bycomparing sum of digits
Convert number to string and split it to array
Use reduce sum all the digits and compare with the array elements
var arr1 = [56, 65, 100, 89, 180, 90];
var arr2 = [11, 11, 1, 17, 9, 9];
console.log(
arr1.sort(
(a, b) =>
a
.toString()
.split("")
.reduce((acc, v) => parseInt(acc) + parseInt(v)) -
b
.toString()
.split("")
.reduce((acc, v) => parseInt(acc) + parseInt(v))
)
);
codepen - https://codepen.io/nagasai/pen/WNeoaEv?editors=1010

Related

Removing values in a range from an array

I want to remove values in a range from an array. For example, removeVals([20, 30, 40, 50, 60, 70], 2, 4) should return the array [20, 30, 70]. How can I solve this problem?
This can be done in one-liner. If you're unfamiliar with arrow functions this might be a bit confusing but I'll put my solution out there anyway.
var removeVals = (array, start, end) => array.filter((item, index) => index < start || index > end);
console.log(removeVals([20, 30, 40, 50, 60, 70], 2, 4)) // [20, 30, 70]
JavaScript's built-in filter function iterates through an array, and passes each item (and the index of said item optionally) into the function that it's provided. If the return value of that function is true, then the item stays in the array, otherwise it is removed. The function that we pass into the filter function only returns true if the index of the current item in the array is less than the beginning of the range or more that the end of the range, therefore removing items that are in the range.
You can use Array#splice, which changes the input array. So you would need to return the modified array.
DEMO
const removeVals = (arr, start, end) => arr.splice(start, end-start+1) && arr;
console.log( removeVals([20, 30, 40, 50, 60, 70], 2, 4) );
This solution works like .filter() demonstrated in tybocopperkettle's answer, but with .flatMap() instead. Using a ternary in .flatMap() gives us an advantage of returning almost any value.
idx < a || idx > z ? num : []
JavaScript
Description
idx < a
If index is less than start...
||
...OR...
idx > z
...if index is greater than end...
? num
...return the value...
:[]
...otherwise return nothing🞾
🞾[] returns as nothing since .flatMap() applies .flat() to whatever it returns.
const arrayA = [20, 30, 40, 50, 60, 70];
const Aa = 2;
const Az = 4;
const arrayB = ['A', 'B', 'C', 'D', 'E', 'F'];
const Ba = 0;
const Bz = 7;
const remVal = (array, a, z) => array
.flatMap((num, idx) =>
idx < a || idx > z ?
num : []
);
console.log(remVal(arrayA, Aa, Az));
console.log(remVal(arrayB, Ba, Bz));
Method-1
This method removes the subset in the range Array[startIx, stopIx] from the source array using the Array.prototype.splice()method.
// INPUT → array[0, array.length - 1]
// OUTPUT → array[0, startIx - 1] U array[stopIx + 1, array.length - 1]
let removeVals = (array, startIx, stopIx) => {
array.splice(startIx, stopIx - startIx + 1);
return array;
}
let array= [20, 30, 40, 50, 60, 70]
console.log(`Result: ${removeVals(array, 2, 4)}`);
Method-2
Create a new array inside the function.
Add the values in the range array[0, startIx - 1] to the new array.
Add values from range array[stopIx+ 1, array.lenght - 1] to the new array.
// INPUT → array[0, array.length - 1]
// OUTPUT → array[0, startIx - 1] U array[stopIx + 1, array.length - 1]
let removeVals = (array, startIx, stopIx) => {
let resultArray = []
for(let i = 0; i < startIx ; ++i)
resultArray.push(array[i])
for(let i = stopIx + 1 ; i < array.length ; ++i)
resultArray.push(array[i])
return resultArray;
}
let array= [20, 30, 40, 50, 60, 70]
console.log(`Result: ${removeVals(array, 2, 4)}`);

Javascript Challenge: Loops - Multiple Conditions - stuck and can't figure this out

I did this module on functions and execution context - all questions have gone well but there is one challenge I have spent a lot of time on and still can't figure it out. Any help will be greatly appreciated. Thank you
Challenge question says:
Write a function addingAllTheWeirdStuff which adds the sum of all the odd numbers in array2 to each element under 10 in array1.
Similarly, addingAllTheWeirdStuff should also add the sum of all the even numbers in array2 to those elements over 10 in array1.
BONUS: If any element in array2 is greater than 20, add 1 to every element in array1.
// Uncomment these to check your work!
// console.log(addingAllTheWeirdStuff([1, 3, 5, 17, 15], [1, 2, 3, 4, 5])); // expected log [10, 12, 14, 23, 21]
// console.log(addingAllTheWeirdStuff([1, 3, 5, 17, 15, 1], [1, 2, 3, 4, 5, 22])); // expected log [11, 13, 15, 46, 44, 11]
// my attempt so far:
function addingAllTheWeirdStuff(array1, array2) {
// ADD CODE HERE
let result = []
for (let i = 0; i < array2.length; i++) {
if (array2[i] > 20) {
result = array1[i] += 1
}
}
for (let i = 0; i < array2.length; i++) {
if (array2[i] % 2 === 0 && array1[i] > 10) {
result = array1[i] + array2[i]
}
}
for (let i = 0; i < array2.length; i++) {
if (array2[i] % 2 !== 0 && array1[i] < 10) {
result = array1[i] + array2[i]
}
}
return result
}
You can easily achieve this using reduce and map array method, with the ternary operator:
const array1 = [1, 3, 5, 17, 15];
const array2 = [1, 2, 3, 4, 5];
function addingAllTheWeirdStuff(array1, array2) {
const oddSum = array2.reduce((sum, current) => current % 2 ? current + sum : 0 + sum, 0)
const oddEven = array2.reduce((sum, current) => current % 2 == 0 ? current + sum : 0 + sum, 0)
return array1.map(num => num < 10 ? num + oddSum : num + oddEven)
}
console.log(addingAllTheWeirdStuff(array1, array2))
If you break the challenge into smaller pieces, you can deconstruct it better and come up with your solutions.
This is what I did... I will be adding more comments shortly with more explanations
I chose to keep using loops as I assumed this was the point of the challenges (to practice for loops, multiple conditions, etc) - In other words, I chose to not use map / reduce on purpose but if that's allowed, use the answer by #charmful0x as it results in less code :)
// function to get sum of all odd numbers in array
function getSumOfAllOddNumbersInArray( elementArray ){
var sumOfOddNumbers = 0;
for (let i = 0; i < elementArray.length; i++) {
// use remainder operator to find out if element is odd or not
if (elementArray[i] % 2 !== 0 ) {
sumOfOddNumbers += elementArray[i];
}
}
return sumOfOddNumbers;
}
// function to get sum of all EVEN numbers in array
function getSumOfAllEvenNumbersInArray( elementArray ){
var sumOfEvenNumbers = 0;
for (let i = 0; i < elementArray.length; i++) {
// use remainder operator to find out if element is odd or not
if (elementArray[i] % 2 === 0 ) {
sumOfEvenNumbers += elementArray[i];
}
}
return sumOfEvenNumbers;
}
// Return true if there is at least one element in array that is greater than 20
function hasElementOverTwenty( elementArray ){
for (let i = 0; i < elementArray.length; i++) {
if (elementArray[i] > 20 ) {
// no need to keep looping, we found one - exit function
return true;
}
}
return false;
}
function addingAllTheWeirdStuff( firstArray, secondArray ){
var sumOfOddNumbersInArray = getSumOfAllOddNumbersInArray( secondArray );
var sumOfEvenNumbersInArray = getSumOfAllEvenNumbersInArray( secondArray );
var needToAddOne = hasElementOverTwenty( secondArray );
for (let i = 0; i < firstArray.length; i++) {
// Challenge One
if (firstArray[i] < 10) {
firstArray[i] = firstArray[i] + sumOfOddNumbersInArray;
} else if (firstArray[i] > 10) {
// Challenge Two
firstArray[i] = firstArray[i] + sumOfEvenNumbersInArray;
}
// bonus
if( needToAddOne ){
firstArray[i]++;
}
}
return firstArray;
}
// Uncomment these to check your work!
console.log(addingAllTheWeirdStuff([1, 3, 5, 17, 15], [1, 2, 3, 4, 5]));
console.log('expected:' + [10, 12, 14, 23, 21] );
console.log(addingAllTheWeirdStuff([1, 3, 5, 17, 15, 1], [1, 2, 3, 4, 5, 22]));
console.log('expected:' + [11, 13, 15, 46, 44, 11] );
Challenge question says: Write a function addingAllTheWeirdStuff which adds the sum of all the odd numbers in array2 to each element under 10 in array1.
Similarly, addingAllTheWeirdStuff should also add the sum of all the even numbers in array2 to those elements over 10 in array1.
BONUS: If any element in array2 is greater than 20, add 1 to every element in array1.

Count pairs in an array in JavaScript

I'm still a junior at web dev and I am trying to solve this problem.
I have to find the number of matching pairs in these arrays:
var ar1 = [10, 20, 20, 10, 10, 30, 50, 10, 20] // return 3 (2 pairs of 10 and 1 pair of 20)
var ar2 = [1, 1, 3, 1, 2, 1, 3, 3, 3, 3] // return 4 (2 pairs of 1 and 2 pairs of 3)
// I started to write my logic below but I'm stuck, could you please help me to solve this problem ?
// The last result I am returning is a filtered array with all the nbs that are superior to 1 and then can't figure out how to get the result of matching pairs :-(
function countPairs(n, ar) {
const count = {};
ar.forEach((nb) => (count[nb] = (count[nb] || 0) + 1));
const values = Object.values(count);
const filter = values.filter((value) => value > 1);
return filter;
}
// 9 and 10 are the length of the arrays
console.log(countPairs(9, ar1))
console.log(countPairs(10, ar2))
Thank you very much for your help!
Perhaps there is a faster/better way to calculate this than this O(2n) solution, but it's something:
var ar1 = [10, 20, 20, 10, 10, 30, 50, 10, 20] // return 3 (2 pairs of 10 and 1 pair of 20)
var ar2 = [1, 1, 3, 1, 2, 1, 3, 3, 3, 3] // return 4 (2 pairs of 1 and 2 pairs of 3)
function countPairs(ar) {
var obj = {};
ar.forEach(item => {
obj[item] = obj[item] ? obj[item] + 1 : 1;
});
return Object.values(obj).reduce((acc, curr) => {
acc += Math.floor(curr / 2)
return acc;
}, 0);
}
console.log(countPairs(ar1))
console.log(countPairs(ar2))
This first calculates the number of occurences for each number and stores them in an Object. Once that is done, we reduce over the values and return the quotient from the division with 2 (to get the number of pairs in total).
Note: I removed the first argument from your function, because the array length is not needed as an argument. It can be obtained from the array you pass directly.
We can achieve this in O(n) time. Maintain an object which keeps track whether a number have been found before, if it was found before, then it makes up a pair, so we increment the pairs count. If not we make the entry of that number in the object 1
function countPairs(arr) {
let pairs = 0;
const obj = {};
arr.forEach(i => {
if (obj[i]) {
pairs += 1;
obj[i] = 0;
} else {
obj[i] = 1;
}
});
return pairs;
}
Simplest solution I can find:
create empty dictionary var t = {}; and use it to count each item in array arr.forEach (i => t[i] = (t[i] || 0) + 1);. After that take all keys Object.values(t) and sum .reduce((acc, p) => acc + ..., 0) each item counts divided by 2 p/2 with Int semantics of course Math.floor(...).
function countPairs(arr) {
var t = {};
arr.forEach (i => t[i] = (t[i] || 0) + 1);
return Object.values(t).reduce((acc, p) => acc + Math.floor(p/2), 0);
}
console.dir(countPairs([1,2,2,2,2,3]));
console.dir(countPairs([1,2,2,2,2,2,3]));
console.dir(countPairs([1,2,2,2,2,2,2,3]));
console.dir(countPairs([10, 20, 20, 10, 10, 30, 50, 10, 20]));
console.dir(countPairs([1, 1, 3, 1, 2, 1, 3, 3, 3, 3]));
First argument in your implementation is not necessary.
Please up-vote if answer was helpful
Concise approach with reduce method
const countPairs = arr => (pairs = [], arr.reduce((p, c) => (p[c] ? (pairs.push([p[c], c]), delete p[c]) : p[c] = c, p), {}), pairs.length)
console.log(countPairs([10, 20, 20, 10, 10, 30, 50, 10, 20]));
So, I wanted a more simpler solution to this problem since I'm just starting to learn to code and I'm teaching my self. I found this solution works perfectly for what you want. I didn't created this solution I found it on the internet(https://www.geeksforgeeks.org/count-equal-element-pairs-in-the-given-array/) I just translated it to JavaScript.
function countDuplicates(n, arr) {
var count = 0;
arr.sort();
for (var i = 0; i < n;) {
if (arr[i] === arr[i + 1]) {
count++;
i = i + 2;
} else {
i++;
}
}
return count;
}
console.log(countDuplicates(9, [10, 20, 20, 10, 10, 30, 50, 10, 20]));
There are some more concise answers here, but here's the solution I have for you:
function countDuplicates(arr) {
var counts = {}, sum = 0;
for (var i = 0; i < arr.length; i++) {
counts[arr[i].toString()] = (counts[arr[i].toString()] || 0) + 1;
}
for (var count in counts) {
if (Object.prototype.hasOwnProperty.call(counts, count)) sum += Math.floor(counts[count] / 2);
}
return sum;
}
console.log(countDuplicates([10, 20, 20, 10, 10, 30, 50, 10, 20]));
I hope I have helped
function numberOfPairs(array) {
let arr = [...array].sort();
let result = 0;
for (let i = 0; i < arr.length; i++) {
if (arr[i] == arr[i + 1]) {
result++;
arr.shift();
}
}
console.log(result);
}
numberOfPairs(['blue', 'blue', 'blue', 1, 2, 5, 2, 1]);

javascript map and reduce array list

I have a list of array in this format
data = [[1,2,3,4,5,6,7,8,9,10],
[11,12,13,14,15,16,17,18,19,20],
[21,22,23,24,25,26,27,28,29,30]]
I want the output in this format
[[11/1, 12/2,13/3,14/4,15/5,16/6,17/7,18/8,19/9,20/10],
[21/11,22/12,23/13,24/14,25/15,26/16,27/17,28/18,29/19,30/20]]
I have used for loop and this is how it looks
const totalData = data.length;
for(var i =0 ; i < totalData ; i++){
for(var j =0; j < data[i].length; j++){
console.log(data[i+1][j]/data[i][j]);
}
}
I want to convert this using javascript map and reduce? is there any possible ways?
Thank you
for loops aren't bad practice, they just don't fit in a functional style of programming. The following solution presupposes that the arrays' lengths are equal:
const data = [
[1,2,3,4,5,6,7,8,9,10],
[11,12,13,14,15,16,17,18,19,20],
[21,22,23,24,25,26,27,28,29,30]
];
const result = data.map((arr, index) => {
const next = data[index + 1];
if (!Array.isArray(next)) {
return;
}
return arr.map((item, i) => next[i] / item);
}).filter(Boolean);
console.log(result);
I am sure you can figure out what to do if the arrays' lengths are not equal.
You could use a single reduce and map the items for a new array.
var data = [[1, 2, 3, 4, 5, 6, 7, 8, 9, 10], [11, 12, 13, 14, 15, 16, 17, 18, 19, 20], [21, 22, 23, 24, 25, 26, 27, 28, 29, 30]],
result = [];
data.reduce((a, b) => (result.push(a.map((c, i) => b[i] / c)), b));
console.log(result);
.as-console-wrapper { max-height: 100% !important; top: 0; }
You need to create separated functions for each task:
/**
* Combine 2 arrays
* #param Array a
* #param Array b
*/
function combineArrays(a, b) {
var combined = [];
for (var i = 0; i < a.length; i++)
combined.push(a[i] / b[i]);
return combined;
}
/**
* Combine an group of arrays
* #param Array group
*/
function combineGroup(group) {
var newGroup = [];
for (var i = 0; i < group.length - 1; i++)
newGroup.push(combineArrays(group[i], group[i + 1]));
return newGroup;
}
The first function combine 2 arrays only.
The second function combine many arrays and return what you want.
if the lengths are not equal, the items in the tail of the longer one are ignored.
data = [
[1,2,3,4,5,6,7,8,9,10],
[11,12,13,14,15,16,17,18,19,20],
[21,22,23,24,25,26,27,28,29,30]
];
result = data.reduce((acc,current,i)=>{
var ret;
if(data[i].length <= data[i-1].length)
ret = data[i].map((item,j)=>(item / data[i-1][j]));
else
ret = data[i-1].map((item,j)=>(data[i][j] / item));
if(i==1)
return [ret]
else
return acc.concat([ret])
})
console.log(result)

Find Missing Numbers from Unsorted Array

I found this JavaScript algorithm excercise:
Question:
From a unsorted array of numbers 1 to 100 excluding one number, how will you find that number?
The solution the author gives is:
function missingNumber(arr) {
var n = arr.length + 1,
sum = 0,
expectedSum = n * (n + 1) / 2;
for (var i = 0, len = arr.length; i < len; i++) {
sum += arr[i];
}
return expectedSum - sum;
}
I wanted to try and make it so you can find multiple missing numbers.
My solution:
var someArr = [2, 5, 3, 1, 4, 7, 10, 15]
function findMissingNumbers(arr) {
var missingNumbersCount;
var missingNumbers = [];
arr.sort(function(a, b) {
return a - b;
})
for(var i = 0; i < arr.length; i++) {
if(arr[i+1] - arr[i] != 1 && arr[i+1] != undefined) {
missingNumbersCount = arr[i+1] - arr[i] - 1;
for(j = 1; j <= missingNumbersCount; j++) {
missingNumbers.push(arr[i] + j)
}
}
}
return missingNumbers
}
findMissingNumbers(someArr) // [6, 8, 9, 11, 12, 13, 14]
Is there a better way to do this? It has to be JavaScript, since that's what I'm practicing.
You could use a sparse array with 1-values at indexes that correspond to values in the input array. Then you could create yet another array with all numbers (with same length as the sparse array), and retain only those values that correspond to an index with a 1-value in the sparse array.
This will run in O(n) time:
function findMissingNumbers(arr) {
// Create sparse array with a 1 at each index equal to a value in the input.
var sparse = arr.reduce((sparse, i) => (sparse[i]=1,sparse), []);
// Create array 0..highest number, and retain only those values for which
// the sparse array has nothing at that index (and eliminate the 0 value).
return [...sparse.keys()].filter(i => i && !sparse[i]);
}
var someArr = [2, 5, 3, 1, 4, 7, 10, 15]
var result = findMissingNumbers(someArr);
console.log(result);
NB: this requires EcmaScript2015 support.
The simplest solution to this problem
miss = (arr) => {
let missArr=[];
let l = Math.max(...arr);
let startsWithZero = arr.indexOf(0) > -1 ? 0 : 1;
for(i = startsWithZero; i < l; i++) {
if(arr.indexOf(i) < 0) {
missArr.push(i);
}
}
return missArr;
}
miss([3,4,1,2,6,8,12]);
Something like this will do what you want.
var X = [2, 5, 3, 1, 4, 7, 10, 15]; // Array of numbers
var N = Array.from(Array(Math.max.apply(Math, X)).keys()); //Generate number array using the largest int from X
Array.prototype.diff = function(a) {
return this.filter(function(i) {return a.indexOf(i) < 0;}); //Return the difference
};
console.log(N.diff(X));
Option 1:
1. create a binary array
2. iterate over input array and for each element mark binary array true.
3. iterate over binary array and find out numbers of false.
Time complexity = O(N)
Space complexity = N
Option 2:
Sort input array O(nLogn)
iterate over sorted array and identify missing number a[i+1]-a[i] > 0
O(n)
total time complexity = O(nlogn) + O(n)
I think the best way to do this without any iterations for a single missing number would be to just use the sum approach.
const arr=[1-100];
let total=n*(n+1)/2;
let totalarray=array.reduce((t,i)=>t+i);
console.log(total-totalarray);
You can try this:
let missingNum= (n) => {
return n
.sort((a, b) => a - b)
.reduce((r, v, i, a) =>
(l => r.concat(Array.from({ length: v - l - 1 }, _ => ++l)))(a[i - 1]),
[]
)
}
console.log(missingNum([1,2,3,4,10]));
Solution to find missing numbers from unsorted array or array containing duplicate values.
Array.prototype.max = function() {
return Math.max.apply(null, this);
};
var array1 = [1, 3, 4, 7, 9];
var n = array1.length;
var totalElements = array1.max(); // Total count including missing numbers. Can use max
var d = new Uint8Array(totalElements)
for(let i=0; i<n; i++){
d[array1[i]-1] = 1;
}
var outputArray = [];
for(let i=0; i<totalElements; i++) {
if(d[i] == 0) {
outputArray.push(i+1)
}
}
console.log(outputArray.toString());
My solution uses the same logic as trincot's answer
The time complexity is O(n)
const check_miss = (n) => {
let temp = Array(Math.max(...n)).fill(0);
n.forEach((item) => (temp[item] = 1));
const missing_items = temp
.map((item, index) => (item === 0 ? index : -1))
.filter((item) => item !== -1);
console.log(missing_items);
};
n = [5, 4, 2, 1, 10, 20, 0];
check_miss(n);

Categories

Resources