Сортировка смешанного массива.
Есть массив, в котором находятся имена файлов. Задача отсортировать массив в алфавитном порядке, то есть так, как эти имена файлов отображаются в файловом менеджере.
Если имена состоят только из букв или только из цифр, то легко:
var myFilteredFiles = ["A", "B", "C", "g10", "g8", "g1", "11", "H"];
myFilteredFiles.sort(function(x, y){
var r = x - y;
if(isNaN(r)){
r = isNaN(x) - isNaN(y);
if(r == 0) r = x.toLocaleLowerCase().localeCompare(y.toLocaleLowerCase());
}
return r;
});
Получим ["1", "8", "10", "11", "A", "B", "C", "H"] Но если в именах встречаются и буквы и цифры, то сортировка не получается: ["A", "B", "C", "g10", "g8", "g1", "11", "H"] -> ["11", "A", "B", "C", "g1", "g10", "g8", "H"]. А должно быть ["11", "A", "B", "C", "g1", "g8", "g10", "H"] |
koros,
нужна так называемая "натуральная сортировка", поищите это на форуме, когда-то об этом была речь, там и код есть. |
koros,
<script>
const collator = new Intl.Collator(["en", "ru"], { numeric: true });
const myFilteredFiles = ["A", "B", "C", "g10", "g8", "g1", "11", "H"];
myFilteredFiles.sort(collator.compare);
document.write(JSON.stringify(myFilteredFiles, "", 4))
</script>
|
рони,
Спасибо. Но у меня ругается на Intl.Collator: Цитата:
|
koros,
а так?
<script>
const sort = (a, b) => a.localeCompare(b, ["en", "ru"], { numeric: true });
const myFilteredFiles = ["A", "B", "C", "g10", "g8", "g1", "11", "H"];
myFilteredFiles.sort(sort);
document.write(JSON.stringify(myFilteredFiles, "", 4))
</script>
|
koros,
на всякий случай https://github.com/wessberg/polyfiller#readme |
Вот, что то такое изобрел. Может пойдет в Adobe
<script>
function nsort (a,b) {
a = a.toLowerCase();
b = b.toLowerCase();
var re = /(\D*)((0*)(\d*))(.*)/;
var ra = re.exec(a)
var rb = re.exec(b)
if (ra[4].length && rb[4].length) {
if(ra[1] === rb[1]) {
if (ra[3].length != rb[3].length) return rb[3].length - ra[3].length
var na = +ra[2]
var nb = +rb[2]
if (na != nb) return na - nb;
} else {
return ra[1]>rb[1]? 1 : (ra[1]<rb[1]? -1 : 0);
}
if (ra[5].length || rb[5].length) return nsort(ra[5], rb[5])
return 0;
}
return a>b? 1 : (a<b? -1 : 0);
}
const arr = ["A", "B", "C", "x1a3", "x1a", "x1b", "x01a", "011", "g10", "x1a02", "g8", "g1", "g01", "g001", "g081", "11", "H", "x1a2", "b0", "b00"]
arr.sort(nsort)
console.log(arr)
document.write(JSON.stringify(arr))
</script>
Предполагается, что x001 < x01 <x1, но x0 < x00 |
Извиняюсь, что долго не отвечал - был далеко от компьютера.
Цитата:
Цитата:
|
koros,
для чего это в конечном итоге? |
Я уже говорил - для Adobe Illustrator-а. С помощью скрипта открываю по очереди файлы в Illustrator-е и обрабатываю, в частности считываю содержимое текстовых фреймов в текстовый файл. Требуется, чтобы файлы обрабатывались в том же порядке, в каком они отображаются в файловом менеджере. Для проверки работы скрипта в адобовской программе удобно использовать adobe extendscript toolkit cc.
|
Я в том смысле - результат работы Эдоб кому-то предназначается в конечном итоге или нет. Если да, то как бы без разницы порядок, потребитель сам будет предоставлять как ему нужно.
Если нет, то ошибки в Эдоб у вас скорее всего связаны с синтаксисом, то есть, вы не портируете предложенное, а используете как есть. |
Цитата:
Цитата:
|
Цитата:
Цитата:
Вот из темы ранее обсуждаемой, это работает, по крайней мере проверялось. Попробуйте, да и в сети готового js-кода по натуральной сортировке много и всякого разного. |
Цитата:
Почему var a = 'B'; var b = 'a8'; a = a.toLowerCase(); b= b.toLowerCase(); var x = a>b? 1 : a<b? -1 : 0; print(x) выдает x = -1 мне никогда не понять. ЗЫ Самое интересное, что var a = 'B'; var b = 'a8'; a = a.toLowerCase(); b= b.toLowerCase(); var c = a>b print (c); var x = a>b? 1 : a<b? -1 : 0; print(x) выдает c = true, а x = -1 |
До меня, наконец, дошел весь ужас ситуации.
Извращенцы из Adobe изгадили оператор ?: Он у них ассоциативен слева-направо!!! x = a>b? 1 : a<b? -1 : 0 выполняется, как x = ( a>b ? 1 : a<b ) ? -1 : 0 со всеми вытекающими. После расстановки скобок должно работать и в браузере и в Адобах
<script>
function nsort (a,b) {
a = a.toLowerCase();
b = b.toLowerCase();
var re = /(\D*)((0*)(\d*))(.*)/;
var ra = re.exec(a)
var rb = re.exec(b)
if (ra[4].length && rb[4].length) {
if(ra[1] === rb[1]) {
if (ra[3].length != rb[3].length) return rb[3].length - ra[3].length
var na = +ra[2]
var nb = +rb[2]
if (na != nb) return na - nb;
} else {
return ra[1]>rb[1]? 1 : (ra[1]<rb[1]? -1 : 0)
}
if (ra[5].length || rb[5].length) return nsort(ra[5], rb[5])
return 0;
}
return a>b? 1 : (a<b? -1 : 0);
}
const arr = ["A", "B", "C", "x1a3", "x1a", "x1b", "x01a", "011", "g10", "x1a02", "g8", "g1", "g01", "g001", "g081", "11", "H", "x1a2", "b0", "b00"]
arr.sort(nsort)
console.log(arr)
document.write(JSON.stringify(arr))
</script>
ЗЫ В документации по ActionScript все равно говорится, что ?: правоассоциатевен The assignment operators and the conditional ( ?: ) operator are right-associative, which means that the operators on the right are processed before operators on the left. https://help.adobe.com/en_US/as3/lea...8a9b90204-7f6c Наверно я чего то не врубаю. var a = 3; var b = 2; var x = a>b? 1 : a<b? -1 : 0; print(x) выдает -1 а var a = 3; var b = 2; var x = a>b? 1 : (a<b? -1 : 0); print(x) выдает 1, как и положено. |
voraa,
Большое спасибо за помощь. Я немного подредактировал ваш скрипт и у меня заработало:
function nsort (a,b) {
a = decodeURIComponent(a.name).toLowerCase();
b = decodeURIComponent(b.name).toLowerCase();
var re = /(\D*)((0*)(\d*))(.*)/;
var ra = re.exec(a);
var rb = re.exec(b);
if (ra[4].length && rb[4].length){
if(ra[1] === rb[1]){
if(ra[3].length != rb[3].length) return rb[3].length - ra[3].length
var na = +ra[2];
var nb = +rb[2];
if(na != nb) return na - nb;
}
else{
return ra[1].localeCompare(rb[1]);
}
if(ra[5].length || rb[5].length) return nsort(ra[5], rb[5]);
return 0;
}
return a.localeCompare(b);
}
decodeURIComponent(a.name).toLowerCase() - потому что у меня в массиве хранятся файлы. Большое спасибо всем поучаствовавшим за помощь. |
| Часовой пояс GMT +3, время: 20:39. |