Dženis H.
Dženis H.

Reputation: 7822

For every condition that ends up being true in all iterations, push the counter value into a new array

I have multiple arrays, but some of them have values of 0 or undefined. What I'm trying to do is, every time a condition is true, push the counter value into a new array.

let array1 = [5, 6, 44, 2, 6];
let array2 = ['', '', '', 5 , 7];

I got this far, but it's returning only unique values. Meaning, let's imagine we have those two arrays above, first having all values - array1, second doesn't - array2 (index 0, 1, 2 is null, but index 3 and 4 has its number values). The function below is returning --> [1, 2].

empNum = (data) => {
let activeArr = [];
let activeOnes = 0;
    for (let i=0; i<data.length; i++) {
        if (active[i] !== 0 && active[i] !== '') {
            activeOnes ++;
            activeArr.push(activeOnes);
        }

    }
    return activeArr;  // [1, 2 ] < -- This is not what I need.
}

In the first three runs, only one array is passing the condition [1, 1, 1], but on the 4th and 5th run both arrays are passing the test, so the next two entries should be [2, 2].

So, what I'm trying to achieve is a new array looking like this - [1, 1, 1, 2, 2].

Note: The number of arrays isn't two. There are many others, all the same length, and the number of them (num of arrays) can grow over time, as well as the number of entries inside every single one, but at the end, they all will still have the same length.

Maybe some other type of a loop? Any suggestions?

Upvotes: 2

Views: 66

Answers (3)

Amiel Martin
Amiel Martin

Reputation: 4814

One approach could be to make a new array for each position you want to count. This makes it easy to count the number of truthy values for each position in the original arrays.

This is fairly straightforward using lodash's zip:

const array1 = [5, 6, 44, 2, 6];
const array2 = ['', '', '', 5 , 7];
const array3 = [1, '', 0, 1, false]

const zipped = _.zip(array1, array2, array3);

// `zipped` should now look like this, where each element
// is an array that represents all of the elements a given
// position from all of the original arrays.
// [
//     [5, "", 1],
//     [6, "", ""],
//     [44, "", 0],
//     [2, 5, 1],
//     [6, 7, false],
// ]

const results = _.map(zipped, (array) => {
    // lodash doesn't seem to have a `count`, but it does have `countBy`
    const counts = _.countBy(array, (element) => new Boolean(element));

    // Here `counts` will be an object showing how many items in the array were `true` and how many were `false`.
    // For example, in the first iteration, it will look like `{ "false": 1, "true": 2 }`

    // So, only return the count that is `true`.
    return counts['true'];    
});

// Here, the results is:
// [2, 1, 1, 3, 2]

This script can be found at https://runkit.com/amiel/5b22dffb85fb2d00128e2217 if you'd like to run it and see the results.

Upvotes: 1

hygull
hygull

Reputation: 8740

@Ray, let suppose I assume your both arrays of same length then the below code will work as you want.

Here, the use of ternary operator(conditional operator) ?: and 2 logical operators &&, || play great roles.The code works for 0, ''as well as for undefined, null also.

Try it online at http://rextester.com/HYR69124.

// empNum() is a function which takes 2 arrays of same length as parameters
var empNum = (data1, data2) => {
    var activeArr = [];

    for (var i=0; i<data1.length; i++) {
        activeArr.push(data1[i] && data2[i] ? 2 : 1); // Using ternary operator ?:
    }
    return activeArr; 
}

// Test 1
var array1= [5, 6, 44, 2, 6];
var array2 = ['', '', '', 5, 7];
console.log(empNum(array1, array2)); //[ 1, 1, 1, 2, 2 ]

// Test 2
console.log(empNum([5, 0, 44, 2, 6], [8, 7, undefined, 5, 7,] )); // [ 2, 1, 1, 2, 2 ]

// Test 3
console.log(empNum(["JavaScript", 0, undefined, null, 6], [8, 7, undefined, 5, 7,] )); // [ 2, 1, 1, 1, 2 ]


// Test 4
console.log(empNum([0, 0, 44, 2, "Python"], [8, 7, undefined, 5, 7,] )); // [ 1, 1, 1, 2, 2 ]

» Output

[ 1, 1, 1, 2, 2 ]
[ 2, 1, 1, 2, 2 ]
[ 2, 1, 1, 1, 2 ]
[ 1, 1, 1, 2, 2 ]

Upvotes: 0

CertainPerformance
CertainPerformance

Reputation: 370859

I think the best thing to do here would be to map both arrays into a single array, after testing for truthyness:

let array1 = [5, 6, 44, 2, 6];
let array2 = ['', '', '', 5 , 7];

const result = array1.map((item1, i) => {
  const item2 = array2[i];
  return Boolean(item1) + Boolean(item2); // gets converted to number
});
console.log(result);

That's assuming that the arrays have the same number of elements, of course. If they don't, you might use Math.max on the lengths of both arrays first.

If you have multiple arrays, put them into a single array first and then iterate over that array:

const arrs = [
  [5, 6, 44, 2, 6],
  ['', '', '', 5 , 7],
];
const { length } = arrs[0];
const result = Array.from(
  { length },
  (_, i) => arrs.reduce((a, arr) => a + Boolean(arr[i]), 0)
);
console.log(result);

Or you might prefer to access each sub-array only once:

const arrs = [
  [5, 6, 44, 2, 6],
  ['', '', '', 5 , 7],
];
const { length } = arrs[0];
const result = [];
arrs.forEach(arr =>
  arr.forEach((item, i) => result[i] = (result[i] || 0) + Boolean(item))
);
console.log(result);

Upvotes: 2

Related Questions