How to create a object using two single arrays? - javascript

I have two arrays. Those are
let x = [1,2,0,4,7,8,9,1,1,1];
let y = [10,50,80,70,906,80,70,80,15,11]
Important : x = y, That means 1 = 10, 2 = 50, 0 = 80 etc...
I want to find minimum and maximum value of x array and want to get y values related to that data, as well as 0 values (min value should greater than 0 value)
expected output is:
let res = {
min: {
minVal: 1,
minvalues: [10, 80, 15, 11]
},
max: {
minVal: 9,
minvalues: [70]
}
empty: [80]
}
Here is what I tried. this way problem is I couldn't get only value from filter method it gives object
const res = x.map((key, index) => {
return {[key]: y[index]};
}, {});
let info = {
min : {},
max : {},
empty : {}
}
let min = Math.min.apply(this, x.filter(Number));
let max = Math.max(...x);
info.min['min'] = min
info.min['minVal'] = res.filter((el, idx) => el[min])`

You could group and collect min and max values, then destrucure the result and build a new object.
const
x = [ 1, 2, 0 , 4, 7, 8, 9, 1 , 1, 1],
y = [10, 50, 80, 70, 906, 80, 70, 80, 15, 11],
{ minVal, maxVal, 0: empty, [minVal]: minvalues, [maxVal]: maxvalues } = x.reduce((r, value, i) => {
(r[value] ??= []).push(y[i]);
if (value && r.minVal > value) r.minVal = value;
if (value && r.maxVal < value) r.maxVal = value;
return r;
}, { minVal: Number.MAX_VALUE, maxVal: -Number.MAX_VALUE })
result = { min: { minVal, minvalues }, max: { maxVal, maxvalues }, empty };
console.log(result);
.as-console-wrapper { max-height: 100% !important; top: 0; }

You can store the indexes of the minimum x values, then use those indexes to get the corresponding y values with Array#map.
let x = [1,2,0,4,7,8,9,1,1,1];
let y = [10,50,80,70,906,80,70,80,15,11];
let minIdx = [0], maxIdx = [0], empty = [];
for (let i = 1; i < x.length; i++) {
if (x[i] === 0) {
empty.push(y[i]);
continue;
}
if (x[i] === x[minIdx[0]]) minIdx.push(i);
else if (x[i] < x[minIdx[0]]) minIdx = [i];
if (x[i] === x[maxIdx[0]]) maxIdx.push(i);
else if (x[i] > x[maxIdx[0]]) maxIdx = [i];
}
let res = {
min : {
minVal: x[minIdx[0]],
minvalues: minIdx.map(i => y[i])
},
max: {
maxVal: x[maxIdx[0]],
maxvalues: maxIdx.map(i => y[i])
},
empty
};
console.log(res);

It looks like you're trying to do everything in one line. Let's examine finding the desired min values as separate steps.
// first remove zero values from the x array (since those appear to get their own special handing in empty
// This returns all values that are not zero in the x array
const cleanX = x.filter(val=>val !== 0);
// now find the minimum of the x array
// the ... operator takes and array and turns it into a list of parameters thus [1,2,3] becomes Math.min(1,2,3)
const xMin = Math.min(...cleanX);
// then get the values associated with the minimum X
// this filter returns only values that match xMin by using the index (position in array) to match the x and y arrays
// we have to run y.filter, to return the values from the y array
const xMinValues = y.filter((yValue, index) => x[index] === xMin);
// a portion of your result would then look like this
const res = {
min: {
minVal: xMin,
minvalues: xMinValues
},
A similar method can be used for max, and empty. But empty will only look for the fixed value of 0.

let x = [1, 2, 0, 4, 7, 8, 9, 1, 1, 1];
let y = [10, 50, 80, 70, 906, 80, 70, 80, 15, 11];
//group by "x" and sort
const group = x
.reduce((a: any, b: number, index: number) => {
const el = a.find((x) => x.value == b);
if (!el) a.push({ value: b, data: [y[index]] });
else el.data.push(y[index]);
return a;
}, [])
.sort((a, b) => a.value - b.value);
//create an object result
const result = {
min: {
minVal: group[0].value == 0 ? group[1].value : group[0].value,
minValues: group[0].value == 0 ? group[1].data : group[1].data,
},
max: {
minVal: group[group.length - 1].value,
minValues: group[group.length - 1].data,
},
empty: group[0].value == 0 ? group[0].data : [],
};

Related

trying to find element of array from which sum of left side of array is equal to sum of right side of array in JavaScript

I am trying to find element of array from which sum of left side of array is equal to sum of right side of array in JavaScript
I am using:
function findEvenIndex(arr)
{
//Code goes here!
let num = 0;
function check(i){
console.log(arr);
console.log(num)
let arrPart1 = arr.slice(0,i).reduce(((a,b)=>a+b),0);
console.log(arrPart1)
let arrPart2 = arr.slice(i+1,arr.length).reduce(((c,d)=>c+d),0);
console.log(arrPart2)
if(arrPart2 === 0){
return -1
}
else if(arrPart1 !== arrPart2){
num++;
check(num);
}
}
return check(num);
}
For array:
[1,100,50,-51,1,1]
Getting:
[ 1, 100, 50, -51, 1, 1 ]
0
0
101
[ 1, 100, 50, -51, 1, 1 ]
1
1
1
Error:
The array was: [1,100,50,-51,1,1]
: expected undefined to equal 1
I'd recommend abandoning the recursive solution and opting for an iterative one - in this situation, it's easier to debug. I've written a function that is easy to understand and can solve your problem here:
function findEvenIndex(arr)
{
for(let i = 0; i < arr.length; i++) {
let leftTotal = arr.slice(0, i).reduce((t, v) => t + v, 0);
let rightTotal = arr.slice(i + 1).reduce((t, v) => t + v, 0);
if (leftTotal === rightTotal) {
return i;
}
}
return -1;
}
First check if the array length is an even number
if (array.length % 2 === 1) {
return false;
}
Slice the array in half and reverse the 2nd half
let half = (array.length / 2);
let sub1 = array.slice(0, half);
let sub2 = array.slice(-half).reverse();
Then filter both and return matches
return sub1.filter((num, idx) => num === sub2[idx]);
const array1 = [1, 100, 50, -51, 1, 1];
const array2 = [5, 62, 8, 0, 0, 15, 62, -5];
const array3 = [0, 1, 0];
const mirroredValues = array => {
let half;
if (array.length % 2 === 1) {
return false;
} else {
half = (array.length / 2);
}
let sub1 = array.slice(0, half);
let sub2 = array.slice(-half).reverse();
return sub1.filter((num, idx) => num === sub2[idx]);
};
console.log(mirroredValues(array1));
console.log(mirroredValues(array2));
console.log(mirroredValues(array3));
I would do it like this:
const findElementIndex = (array, index = 0) => {
let arr_part_1 = array.slice(0, index).reduce(((a, b) => a + b), 0);
let arr_part_2 = array.slice(index + 1, array.length).reduce(((a, b) => a + b), 0);
return arr_part_1 === arr_part_2 ? index : index === array.length ? -1 : findElementIndex(array, index + 1);
};
console.log('Example 1: ', findElementIndex([1, 1, 10, 2]));
console.log('Example 2: ', findElementIndex([1, 1, 1, 10, 2]));
console.log('Example 3: ', findElementIndex([100, 1, 100]));
That one could be better from performance point of view (reduce only once)
function inTheMiddle(arr) {
let rightSum = arr.slice(2).reduce((total, item) => total + item, 0);
let leftSum = arr[0];
console.log(leftSum, rightSum);
for (let i = 2; i < arr.length; i++) {
if (leftSum === rightSum) {
return i-1;
}
leftSum += arr[i-1];
rightSum -= arr[i];
console.log(leftSum, rightSum);
}
return -1;
}
console.log("In the middle:", inTheMiddle([1,100,50,-51,1,1]))

Multiplying each object properties by 2 and creating new object from the result

Is this a good practice multiplying each object properties by 2 without mutating original object or there's easy way of achieving same result?
let salaires = {
'john': [20, 8, 5, 90, 22],
'pete': [50, 5, 400, 3],
'seun': 40
}
let x = []
let newArr = []
let salaryNew = {}
for (let [key, value] of Object.entries(salaires)) {
newArr.push([key, value])
}
for (let i = 0; i < newArr.length; i++) {
let x = newArr[i].flat(10)
console.log(x)
let s = x.slice(0, 1)
let see = x.map(function (i) {
return i * 2
})
let finalResult = s.concat(see.slice(1))
salaryNew[`${finalResult[0]}`] = see.slice(1)
console.log(salaryNew)
}
Set the properties of the new object using bracket notation and map the array.
let salaires = {
'john': [20, 8, 5, 90, 22],
'pete': [50, 5, 400, 3],
'seun': 40
},
salaryNew = {}
for (let [key, value] of Object.entries(salaires)) {
salaryNew[key] = Array.isArray(value) ? value.map(n => 2 * n) : 2 * value;
}
console.log(salaryNew);
Notice, that multitype data increases complexity, it's recommended to use a single type only, you could wrap the single value into an array as well.
Take all the keys from the object with Object.keys, then call reduce over them and multiply each property value depending on if it's an array or a number
const K = 2;
const result = Object.keys(salaries).reduce((acc, name) => {
const salary = salaries[name];
if (salary instanceof Array) {
acc[name] = salary.map(item => item * K);
} else {
acc[name] = salary * K;
}
return acc;
}, {});

How to add number in dynamic object's fields and remove empty fields using lodash?

INPUT:
let counts = { first_counts: 10, second_counts: 20, third_counts: 0 };
BRIEF:
I have object and all fields/keys are dynamic
Add/plus 10 to each field/key's value
Remove empty fields/keys
I want to do it using lodash
EXPECTED RESULT:
{ first_counts: 20, second_counts: 30 }
WORKING CODE USIGN FOR AND IF:
let counts = { first_counts: 10, second_counts: 20, third_counts: 0 };
let newCounts = {};
for (let k in counts) {
if (counts[k]) newCounts[k] = counts[k] + 10;
}
console.log(newCounts);
// result: { "first_counts": 20, "second_counts": 30 }
Is there any function to do this easily in lodash?
You could make that chained (to help making one-liner). First filter key-value pairs which have falsy value. Finally map values and add 10 to each
const counts = { first_counts: 10, second_counts: 20, third_counts: 0 };
const res = _.chain(counts)
.pickBy(Boolean)
.mapValues((v) => v + 10)
.value();
console.log(res);
<script src="https://cdn.jsdelivr.net/npm/lodash#4.17.20/lodash.min.js"></script>
Using reduce you can do that.
const counts = { first_counts: 10, second_counts: 20, third_counts: 0 };
_.reduce(counts,(result, value, key) => {
if(value) result[key] = value + 10;
return result;
}, {});
one line solution
let counts = { first_counts: 10, second_counts: 20, third_counts: 0 };
let newCounts = _.reduce(counts, (r, v, k)=> v ? {...r, [k]: v + 10} : r, {});
r - result,
v - value,
k - key

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]);

To find minimum elements in array which has sum equals to given value

I am trying to find out the minimum elements in array whose sum equals
the given input.I tried for few input sum but was able to find only a
pair in first case while I need to implement for more than just a pair.
var arr = [10, 0, -1, 20, 25, 30];
var sum = 45;
var newArr = [];
console.log('before sorting = ' + arr);
arr.sort(function(a, b) {
return a - b;
});
console.log('after sorting = ' + arr);
var l = 0;
var arrSize = arr.length - 1;
while (l < arrSize) {
if (arr[l] + arr[arrSize] === sum) {
var result = newArr.concat(arr[l], arr[arrSize]);
console.log(result);
break;
} else if (arr[l] + arr[arrSize] > sum) {
arrSize--;
} else {
l++;
}
}
Input Array : [10, 0, -1, 20, 25, 30]
Required Sum: 45
Output: [20, 25]
I am trying for
Required Sum : 59
Output: [10, -1, 20, 30]
This can be viewed as an optimization problem which lends itself well to dynamic programming.
This means you would break it up into a recursion that tries to find the minimum length of increasingly smaller arrays with the sum adjusted for what's been removed. If your array is [10, 0, -1, 20, 25, 30] with a sum of 59 you can think of shortest as the min of:
[10, ... shortest([ 0, -1, 20, 25, 30], 49)
[0, ... shortest([10, 20, 25, 30], 49), 59)
[-1, ... shortest([10, 0, 20, 25, 30], 60)
... continue recursively
with each recursion, the array gets shorter until you are left with one element. Then the question is whether that element equals the number left over after all the subtractions.
It's easier to show in code:
function findMinSum(arr, n){
if(!arr) return
let min
for (let i=0; i<arr.length; i++) {
/* if a number equals the sum, it's obviously
* the shortest set, just return it
*/
if (arr[i] == n) return [arr[i]]
/* recursively call on subset with
* sum adjusted for removed element
*/
let next = findMinSum(arr.slice(i+1), n-arr[i])
/* we only care about next if it's shorter then
* the shortest thing we've seen so far
*/
if (next){
if(min === undefined || next.length < min.length){
min = [arr[i], ...next]
}
}
}
return min && min /* if we found a match return it, otherwise return undefined */
}
console.log(findMinSum([10, 0, -1, 20, 25, 30], 59).join(', '))
console.log(findMinSum([10, 0, -1, 20, 25, 30], 29).join(', '))
console.log(findMinSum([10, 0, -1, 20, 25, 30], -5)) // undefined when no sum
This is still pretty computationally expensive but it should be much faster than finding all the subsets and sums.
One option is to find all possible subsets of the array, and then filter them by those which sum to the required value, and then identify the one(s) with the lowest length:
const getMinElementsWhichSum = (arr, target) => {
const subsets = getAllSubsetsOfArr(arr);
const subsetsWhichSumToTarget = subsets.filter(subset => subset.reduce((a, b) => a + b, 0) === target);
return subsetsWhichSumToTarget.reduce((a, b) => a.length < b.length ? a : b, { length: Infinity });
};
console.log(getMinElementsWhichSum([10, 0, -1, 20, 25, 30], 45));
console.log(getMinElementsWhichSum([10, 0, -1, 20, 25, 30], 59));
// https://stackoverflow.com/questions/5752002/find-all-possible-subset-combos-in-an-array
function getAllSubsetsOfArr(array) {
return new Array(1 << array.length).fill().map(
(e1,i) => array.filter((e2, j) => i & 1 << j));
}
Try this,
var arr = [10, 0, -1, 20, 25, 30];
var sum = 29;
var newArr = [];
var sum_expected = 0;
var y = 0;
while (y < arr.length) {
for (let i = 0; i < arr.length; i++) {
var subArr = [];
sum_expected = arr[i];
if (arr[i] != 0) subArr.push(arr[i]);
for (let j = 0; j < arr.length; j++) {
if (i == j)
continue;
sum_expected += arr[j];
if (arr[j] != 0) subArr.push(arr[j]);
if (sum_expected == sum) {
var result = arr.filter((el)=>(subArr.indexOf(el) > -1));
!newArr.length ? newArr = result : result.length < newArr.length ? newArr = result : 1;
break;
}
}
}
let x = arr.shift();
arr.push(x);
y++;
}
if (newArr.length) {
console.log(newArr);
} else {
console.log('Not found');
}

Categories

Resources