Сортировка массива Javascript и уникальные
У меня есть такой массив JavaScript:
var myData=['237','124','255','124','366','255'];
Мне нужно, чтобы элементы массива были уникальными и отсортированы:
myData[0]='124';
myData[1]='237';
myData[2]='255';
myData[3]='366';
Несмотря на то, что члены массива выглядят как целые числа, они не целые числа, так как я уже преобразовал их в строку:
var myData[0]=num.toString();
//...and so on.
Есть ли способ выполнить все эти задачи в JavaScript?
Ответы
Ответ 1
Это на самом деле очень просто. Намного легче найти уникальные значения, если сначала отсортировать значения:
function sort_unique(arr) {
if (arr.length === 0) return arr;
arr = arr.sort(function (a, b) { return a*1 - b*1; });
var ret = [arr[0]];
for (var i = 1; i < arr.length; i++) { //Start loop at 1: arr[0] can never be a duplicate
if (arr[i-1] !== arr[i]) {
ret.push(arr[i]);
}
}
return ret;
}
console.log(sort_unique(['237','124','255','124','366','255']));
//["124", "237", "255", "366"]
Ответ 2
Это может быть адекватным в обстоятельствах, когда вы не можете заранее определить функцию (например, в букмарклет):
myData.sort().filter(function(el,i,a){if(i==a.indexOf(el))return 1;return 0})
Ответ 3
function sort_unique(arr) {
return arr.sort().filter(function(el,i,a) {
return (i==a.indexOf(el));
});
}
Ответ 4
Здесь мой (более современный) подход с использованием Array.protoype.reduce()
:
[2, 1, 2, 3].reduce((a, x) => a.includes(x) ? a : [...a, x], []).sort()
// returns [1, 2, 3]
Изменить: Более эффективная версия, указанная в комментариях:
arr.sort().filter((x, i, a) => !i || x != a[i-1])
Ответ 5
Попробуйте использовать внешнюю библиотеку, например underscore
var f = _.compose(_.uniq, function(array) {
return _.sortBy(array, _.identity);
});
var sortedUnique = f(array);
Это зависит от _.compose
, _.uniq
, _.sortBy
, _.identity
Смотрите live пример
Что он делает?
Нам нужна функция, которая принимает массив, а затем возвращает отсортированный массив с удаленными уникальными элементами. Эта функция должна выполнять две вещи: сортировка и создание уникального массива.
Это хорошая работа для композиции, поэтому мы вместе составляем уникальную функцию сортировки. _.uniq
можно просто применить к массиву с одним аргументом, поэтому он просто передается в _.compose
Для функции _.sortBy необходим условный функционал сортировки. он ожидает функцию, которая возвращает значение, и массив будет сортироваться по этому значению. Поскольку значение, которое мы заказываем, это значение в массиве, мы можем просто передать функцию _.identity.
Теперь мы имеем композицию функции, которая (принимает массив и возвращает уникальный массив) и функцию, которая (принимает массив и возвращает отсортированный массив, отсортированный по их значениям).
Мы просто применяем композицию в массиве, и у нас есть наш уникальный сортированный массив.
Ответ 6
Эта функция не сбой для более двух значений дубликатов:
function unique(arr) {
var a = [];
var l = arr.length;
for(var i=0; i<l; i++) {
for(var j=i+1; j<l; j++) {
// If a[i] is found later in the array
if (arr[i] === arr[j])
j = ++i;
}
a.push(arr[i]);
}
return a;
};
Ответ 7
Как насчет:
array.sort().filter(function(elem, index, arr) {
return index == arr.length - 1 || arr[index + 1] != elem
})
Это похоже на ответ @loostro, но вместо использования indexOf, который будет повторять массив для каждого элемента, чтобы проверить, что первый найден, он просто проверяет, что следующий элемент отличается от текущего.
Ответ 8
Теперь вы можете достичь результата только в одной строке кода.
Используя новый набор, чтобы уменьшить массив до уникального набора значений.
Примените метод sort после заказа строковых значений.
var myData=['237','124','255','124','366','255']
var uniqueAndSorted = [...new Set(myData)].sort()
ОБНОВЛЕНО для новых методов, введенных в JavaScript с момента запроса.
Ответ 9
Способ использования пользовательской функции сортировки
//func has to return 0 in the case in which they are equal
sort_unique = function(arr,func) {
func = func || function (a, b) {
return a*1 - b*1;
};
arr = arr.sort(func);
var ret = [arr[0]];
for (var i = 1; i < arr.length; i++) {
if (func(arr[i-1],arr[i]) != 0)
ret.push(arr[i]);
}
}
return ret;
}
Пример: порядок desc для массива объектов
MyArray = sort_unique(MyArray , function(a,b){
return b.iterator_internal*1 - a.iterator_internal*1;
});
Ответ 10
Нет избыточного массива "return", нет встроенных модулей ECMA5 (я уверен!) и прост для чтения.
function removeDuplicates(target_array) {
target_array.sort();
var i = 0;
while(i < target_array.length) {
if(target_array[i] === target_array[i+1]) {
target_array.splice(i+1,1);
}
else {
i += 1;
}
}
return target_array;
}
Ответ 11
Думаю, я опубликую этот ответ для некоторого разнообразия. Этот метод очистки дубликатов - это то, что я выбрал для проекта во Flash. В настоящее время я работаю примерно месяц назад.
Что вы делаете, это сделать объект и заполнить его как ключом, так и значением, использующим каждый элемент массива. Поскольку дубликаты ключей отбрасываются, дубликаты удаляются.
var nums = [1, 1, 2, 3, 3, 4, 5, 5, 6, 7, 7, 8, 9, 9, 10];
var newNums = purgeArray(nums);
function purgeArray(ar)
{
var obj = {};
var temp = [];
for(var i=0;i<ar.length;i++)
{
obj[ar[i]] = ar[i];
}
for (var item in obj)
{
temp.push(obj[item]);
}
return temp;
}
Там уже 5 других ответов, поэтому я не вижу необходимости публиковать функцию сортировки.
Ответ 12
// Another way, that does not rearrange the original Array
// and spends a little less time handling duplicates.
function uniqueSort(arr, sortby){
var A1= arr.slice();
A1= typeof sortby== 'function'? A1.sort(sortby): A1.sort();
var last= A1.shift(), next, A2= [last];
while(A1.length){
next= A1.shift();
while(next=== last) next= A1.shift();
if(next!=undefined){
A2[A2.length]= next;
last= next;
}
}
return A2;
}
var myData= ['237','124','255','124','366','255','100','1000'];
uniqueSort(myData,function(a,b){return a-b})
// the ordinary sort() returns the same array as the number sort here,
// but some strings of digits do not sort so nicely numerical.
Ответ 13
Функция sort() только хороша, если ваш номер имеет одну и ту же цифру, например:
var myData = ["3","11","1","2"]
вернется;
var myData = ["1","11","2","3"]
и здесь улучшение функции от mrmonkington
myData.sort().sort(function(a,b){return a - b;}).filter(function(el,i,a){if(i==a.indexOf(el) & el.length>0)return 1;return 0;})
вышеуказанная функция также удалит пустой массив, и вы можете проверить демонстрацию ниже
http://jsbin.com/ahojip/2/edit
Ответ 14
Вот простой лайнер с O(N)
, предполагающий:
- вы находитесь в современном браузере или в node.js
- ваш массив - это строки.
Тогда
> Object.keys([{}].concat(['a', 'b', 'a']).reduce((l,r) => l[r] = l ))
[ 'a', 'b' ]
Объяснение
Исходный набор данных, предположим, что он поступает от внешней функции
let data = ['a', 'b', 'a']
Мы хотим добавить объект к фронту массива
let setup = [{}].concat(data)
Далее мы хотим уменьшить массив до одного значения.
На предыдущем шаге мы добавили объект в массив, чтобы на этом шаге мы могли привязать все значения к этому объекту, как к ключам. Конечным результатом является объект с уникальным набором ключей.
let reduced = setup.reduce((l,r) => l[r] = l)
Мы устанавливаем l[r] = l
, потому что в javascript значение выражения присваивания возвращается, когда оператор присваивания используется как выражение.
Далее мы хотим получить ключи этого объекта
let keys = Object.keys(setup)
Какой набор уникальных значений исходного массива
['a', 'b']
Ответ 15
Я боюсь, что вы не можете объединить эти функции, т.е. вы должны сделать что-то вроде этого: -
myData.unique().sort();
В качестве альтернативы вы можете реализовать своего рода sortedset (как доступно на других языках) - который несет как понятие сортировки, так и удаления дубликатов, как вам нужно.
Надеюсь, что это поможет.
Литература: -
Array.sort
Array.unique