Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

filtering an array of strings

I need to filter an array and I am totally drawing a blank on how to do so.

I need to filter out the largest numbers. A number can be deemed larger when the first number is 'XXXX' and the second is 'XXXX-1', then the second number is larger. Or it can be deemed larger if the first number is 'XXXX-1' and the second is 'XXXX-2', then the second is largest.

In the case that the number has no version thats larger, in the example below lets look at '2234'. There is no '2234-1', so thus, '2234' is the largest of its kind and should be removed.

So given this array (of strings) as an example:

['7851', '7851-2', '7851-1', '2234', '2235', '2235-1']

I would expect this result:

['7851', '7851-1', '2235']
like image 816
Houssem Chlegou Avatar asked Feb 24 '17 09:02

Houssem Chlegou


3 Answers

You could group the items and sort it later, then pop the last and filter the original array with a look up for the saved value.

var array = ['7851', '7851-2', '7851-1', '2234', '2235', '2235-1'],
    result = function (array) {
        var groups = Object.create(null);

        array.forEach(function (a) {
            var key = a.split('-')[0];
            groups[key] = groups[key] || [];
            groups[key].push(a);
        });

        Object.keys(groups).forEach(function (k) {
            groups[k].sort().pop();
        });

        return array.filter(function (a) {
            return groups[a.split('-')[0]].some(function (b) { return a === b; });
        });
    }(array);

console.log(result);
like image 76
Nina Scholz Avatar answered Sep 29 '22 13:09

Nina Scholz


A combination of reduce and map would do the job in one go:

let a = ["7851", "7851-2", "7851-1", "2234", "2235", "2235-1"];
let b = [...a.reduce((a, b) => {
  let s = b.split("-");
  a.set(s[0], (!a.has(s[0]) ? [(s[1] || 0)] : a.get(s[0]).concat((s[1] || 0))));
  return a;
}, new Map()).entries()].map(k => {
  k[1].sort((a, b) => b < a).pop();
  if (k[1].length === 0) return;
  return k[1].map(f => k[0] + (f > 0 ? "-" + f : ""))
}).filter(v => v).reduce((a, b) => a.concat(b), []);
console.log(b);
like image 38
baao Avatar answered Sep 29 '22 11:09

baao


Using JavaScript you can try the code below:

var numbers = ["7851", "7851-2", "7851-1", "2234", "2235", "2235-1"];
var arr = [];
for (var i = 0; i < numbers.length; i++)
{
    // The first part of the number defines the hash key
    var hash_key = numbers[i].split("-")[0];
    if (arr[hash_key] === undefined)
    {
        arr[hash_key] = [];
    }
    arr[hash_key][arr[hash_key].length] = numbers[i];
}

// sort each array - 
// then access all elements but the last and populate numbers array 
var numbers = [];
var j = 0;
for (var k in arr) {            
    arr[k].sort();
    for (var i = 0; i < arr[k].length - 1; i++) {
        numbers[j] = arr[k][i];
        j++;                
    }
}

console.log(numbers);
like image 25
Giorgos Betsos Avatar answered Sep 29 '22 12:09

Giorgos Betsos