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']
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']
Share
Improve this question
edited Feb 24, 2017 at 9:50
gyre
16.8k4 gold badges40 silver badges47 bronze badges
asked Feb 24, 2017 at 9:03
Houssem ChlegouHoussem Chlegou
1491 silver badge13 bronze badges
0
4 Answers
Reset to default 5You 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);
A bination 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);
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);
All the current solutions assume that the numbers will be XXXX-Y
where Y
is always a number between 0
and 9
(maybe it is the requirement, but it is not clear in the question). In this case, we are working with Strings
, so 1234-15
will be lower than 1234-7
. It is needed to sort the Arrays
in a numeric way. If we use the next Array
with the current solutions on the page, this will be the results:
var array = ["14670-20", "7851", "7851-2", "14670-10", "7851-1", "2234", "2235", "2235-1", "14670-7"];
// ["14670-20", "7851", "14670-10", "7851-1", "2235"]
// ["14670-10", "14670-20", "7851", "7851-1", "2235"]
// ["2235", "7851", "7851-1", "14670-10", "14670-20"]
The number 14670-7
has been dropped because, as String
, it is bigger than 14670-10
and 14670-20
.
Here you have a solution that orders the Array
first, and next reduce the values to get the lower ones (this solution changes the order of the original Array
)
var array = ["14670-20", "7851", "7851-2", "14670-10", "7851-1", "2234", "2235", "2235-1", "14670-7"];
function getFilteredArray (array) {
var reg = /^(\d+)\-?(\d*)$/;
var current = "";
var sort = function (a, b) {
var ra = a.match(reg), rb = b.match(reg);
if (ra[1] === rb[1]) { return (+ra[2]) - (+rb[2]); }
return (+ra[1]) - (+rb[1]);
}
return array.sort(sort).reduce(function (bundle, item, index) {
var number = item.split("-")[0];
bundle.splice((current !== number) ? -1 : bundle.length, 1, item);
current = number;
return bundle;
}, []).slice(0, -1);
}
console.log( getFilteredArray(array) );
This another solution is a little longer but it keeps the order of the original Array
:
var array = ["14670-20", "7851", "7851-2", "14670-10", "7851-1", "2234", "2235", "2235-1", "14670-7"];
function getFilteredArray (array) {
var reg = /^(\d+)\-?(\d*)$/;
var sort = function (a, b) {
var ra = a.match(reg), rb = b.match(reg);
if (ra[1] === rb[1]) { return (+ra[2]) - (+rb[2]); }
return (+ra[1]) - (+rb[1]);
}
var objs = array.reduce(function (bundle, item) {
var number = item.split("-")[0];
bundle[number] = bundle[number] || [];
bundle[number].push(item);
return bundle;
}, {});
for (var prop in objs) {
var last = objs[prop].sort(sort).pop();
array.splice(array.indexOf(last), 1);
}
return array;
}
console.log( getFilteredArray(array) );
发布者:admin,转转请注明出处:http://www.yc00.com/questions/1745300777a4621421.html
评论列表(0条)