Javascript-форум (https://javascript.ru/forum/)
-   Общие вопросы Javascript (https://javascript.ru/forum/misc/)
-   -   Сортировка смешанного массива. (https://javascript.ru/forum/misc/80845-sortirovka-smeshannogo-massiva.html)

koros 13.08.2020 15:56

Сортировка смешанного массива.
 
Есть массив, в котором находятся имена файлов. Задача отсортировать массив в алфавитном порядке, то есть так, как эти имена файлов отображаются в файловом менеджере.
Если имена состоят только из букв или только из цифр, то легко:
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"]

laimas 13.08.2020 16:00

koros,
нужна так называемая "натуральная сортировка", поищите это на форуме, когда-то об этом была речь, там и код есть.

рони 13.08.2020 16:39

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>

koros 14.08.2020 10:30

рони,
Спасибо. Но у меня ругается на Intl.Collator:
Цитата:

Intl is undefined
Забыл сказать (может это важно) скрипт запускается из Adobe ExtendScript Toolkit и потом будет применяться в Adobe Illustrator.

рони 14.08.2020 10:59

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>

рони 14.08.2020 11:09

koros,
на всякий случай https://github.com/wessberg/polyfiller#readme

voraa 14.08.2020 12:05

Вот, что то такое изобрел. Может пойдет в 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 17.08.2020 10:01

Извиняюсь, что долго не отвечал - был далеко от компьютера.
Цитата:

Сообщение от рони (Сообщение 527957)
koros,
а так?

Тоже не работает. Выделяет ">" и говорит, что "Cannot assign value"

Цитата:

Сообщение от voraa (Сообщение 527960)
Вот, что то такое изобрел. Может пойдет в Adobe

К сожалению, не получается. Сделал в конце вывод через алерт - каждый раз выводит отличную от предыдущей последовательность элементов массива arr и, естественно, неотсортированную(. Если не сложно - проверьте, пожалуйста, на adobe extendscript toolkit cc.

laimas 17.08.2020 11:07

koros,
для чего это в конечном итоге?

koros 17.08.2020 11:42

Я уже говорил - для Adobe Illustrator-а. С помощью скрипта открываю по очереди файлы в Illustrator-е и обрабатываю, в частности считываю содержимое текстовых фреймов в текстовый файл. Требуется, чтобы файлы обрабатывались в том же порядке, в каком они отображаются в файловом менеджере. Для проверки работы скрипта в адобовской программе удобно использовать adobe extendscript toolkit cc.

laimas 17.08.2020 12:02

Я в том смысле - результат работы Эдоб кому-то предназначается в конечном итоге или нет. Если да, то как бы без разницы порядок, потребитель сам будет предоставлять как ему нужно.
Если нет, то ошибки в Эдоб у вас скорее всего связаны с синтаксисом, то есть, вы не портируете предложенное, а используете как есть.

koros 17.08.2020 12:47

Цитата:

Сообщение от laimas (Сообщение 528044)
Я в том смысле - результат работы Эдоб кому-то предназначается в конечном итоге или нет. Если да, то как бы без разницы порядок, потребитель сам будет предоставлять как ему нужно.

Честно говоря, я недопонял вашего вопроса. Результат работы нужен мне. Порядок, в котором обрабатываются файлы важен тоже мне. Переставлять что-либо после работы скрипта я не хочу. Что не так? Или мне надо что-то сделать скриптом, а остальное - в ручную?
Цитата:

Сообщение от laimas (Сообщение 528044)
Если нет, то ошибки в Эдоб у вас скорее всего связаны с синтаксисом, то есть, вы не портируете предложенное, а используете как есть.

В Adobe у меня нет ошибок (я имею в виду то, что предложил уважаемый voraa), просто скрипт не делает почему-то то, что надо. Если имеются в виду ошибки при работе скрипта от уважаемого рони, то непонятно, как портировать его скрипт. В Adobe используются стандартные конструкции языка JavaScript и специфические для его программ. Конкретно в сабже используются стандартные конструкции языка JavaScript.

laimas 17.08.2020 14:38

Цитата:

Сообщение от koros
Честно говоря, я недопонял вашего вопроса.

То есть, результат в конечном итоге будет передан на сервер. Ну если для себя, значит нет.
Цитата:

Сообщение от koros
В Adobe у меня нет ошибок

Я не специалист ActionScript, но когда-то что-от простое для Фотошоп писал, из под консоли ActionScript, которая также устанавливалась с пакетом программ. Вроде бы как в ActionScript есть строгая типизация, то есть, например, объявление переменной, это var a:Array = ... Или это старое и теперь не так, или я просто с чем-то путаю?

Вот из темы ранее обсуждаемой, это работает, по крайней мере проверялось. Попробуйте, да и в сети готового js-кода по натуральной сортировке много и всякого разного.

voraa 17.08.2020 17:31

Цитата:

Сообщение от koros
Если не сложно - проверьте, пожалуйста, на adobe extendscript toolkit cc.

Проверил и немного охренел
Почему

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

voraa 17.08.2020 18:30

До меня, наконец, дошел весь ужас ситуации.
Извращенцы из 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, как и положено.

koros 18.08.2020 09:22

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, время: 10:04.