1 (изменено: Phoenixxx_Czar, 2019-03-22 14:20:02)

Тема: AKH: Сортировка массива.

Доброго времени суток, возникла такая проблемка, есть массив, его нужно отсортировать по "rankNum" допустим.
На просторах интернета нашел функцию "SortArray2D", но она как-то криво отсортировала.

Сам массив:

+ открыть спойлер

[{'id': '43', 'isAFK': '1', 'nick': 'Thiago_Montesdeoca', 'probation': '1', 'rankName': 'Lieutenant-General/Commandant', 'rankNum': '14'}, {'id': '56', 'isAFK': '0', 'nick': 'Connor_Dixon', 'probation': '1', 'rankName': 'Recruit Guard', 'rankNum': '1'}, {'id': '96', 'isAFK': '0', 'nick': 'Markus_Pride', 'probation': '1', 'rankName': 'Lieutenant-General/Commandant', 'rankNum': '14'}, {'id': '133', 'isAFK': '0', 'nick': 'Subaru_Heys', 'probation': '1', 'rankName': 'Recruit Guard', 'rankNum': '1'}, {'id': '219', 'isAFK': '0', 'nick': 'Stefan_Salvatoree', 'probation': '0', 'rankName': 'Recruit Guard', 'rankNum': '1'}, {'id': '278', 'isAFK': '0', 'nick': 'Nikita_Arbys', 'probation': '1', 'rankName': 'Recruit Guard', 'rankNum': '1'}, {'id': '287', 'isAFK': '0', 'nick': 'August_Manana', 'probation': '1', 'rankName': 'Recruit Guard', 'rankNum': '1'}, {'id': '302', 'isAFK': '0', 'nick': 'Rick_Leon', 'probation': '1', 'rankName': 'General', 'rankNum': '15'}, {'id': '321', 'isAFK': '0', 'nick': 'Danilich_Burmatov', 'probation': '1', 'rankName': 'Recruit Guard', 'rankNum': '1'}, {'id': '326', 'isAFK': '0', 'nick': 'Lames_Santa', 'probation': '1', 'rankName': 'Recruit Guard', 'rankNum': '1'}, {'id': '330', 'isAFK': '0', 'nick': 'Ollie_Patterson', 'probation': '1', 'rankName': 'Specialist ||', 'rankNum': '5'}, {'id': '336', 'isAFK': '0', 'nick': 'Alex_Former', 'probation': '1', 'rankName': 'Recruit Guard', 'rankNum': '1'}]

Win10: LTSC (21H2); AHK: ANSI (v1.1.36.02)

2

Re: AKH: Сортировка массива.

Как-то так:

json = [{'id': '43', 'isAFK': '1', 'nick': 'Thiago_Montesdeoca', 'probation': '1', 'rankName': 'Lieutenant-General/Commandant', 'rankNum': '14'}, {'id': '56', 'isAFK': '0', 'nick': 'Connor_Dixon', 'probation': '1', 'rankName': 'Recruit Guard', 'rankNum': '1'}, {'id': '96', 'isAFK': '0', 'nick': 'Markus_Pride', 'probation': '1', 'rankName': 'Lieutenant-General/Commandant', 'rankNum': '14'}, {'id': '133', 'isAFK': '0', 'nick': 'Subaru_Heys', 'probation': '1', 'rankName': 'Recruit Guard', 'rankNum': '1'}, {'id': '219', 'isAFK': '0', 'nick': 'Stefan_Salvatoree', 'probation': '0', 'rankName': 'Recruit Guard', 'rankNum': '1'}, {'id': '278', 'isAFK': '0', 'nick': 'Nikita_Arbys', 'probation': '1', 'rankName': 'Recruit Guard', 'rankNum': '1'}, {'id': '287', 'isAFK': '0', 'nick': 'August_Manana', 'probation': '1', 'rankName': 'Recruit Guard', 'rankNum': '1'}, {'id': '302', 'isAFK': '0', 'nick': 'Rick_Leon', 'probation': '1', 'rankName': 'General', 'rankNum': '15'}, {'id': '321', 'isAFK': '0', 'nick': 'Danilich_Burmatov', 'probation': '1', 'rankName': 'Recruit Guard', 'rankNum': '1'}, {'id': '326', 'isAFK': '0', 'nick': 'Lames_Santa', 'probation': '1', 'rankName': 'Recruit Guard', 'rankNum': '1'}, {'id': '330', 'isAFK': '0', 'nick': 'Ollie_Patterson', 'probation': '1', 'rankName': 'Specialist ||', 'rankNum': '5'}, {'id': '336', 'isAFK': '0', 'nick': 'Alex_Former', 'probation': '1', 'rankName': 'Recruit Guard', 'rankNum': '1'}]

json := StrReplace(json, "'", """")
key := "rankNum"

script =
(
var sJson = '%json%';
var obj = JSON.parse(sJson);
obj.sort(function (a, b) {
  if (a.%key% < b.%key%)
    return -1;
  if (a.%key% > b.%key%)
    return 1;
  return 0;
});
JSON.stringify(obj);
)

document := ComObjCreate("htmlfile")
document.write("<meta http-equiv='X-UA-Compatible' content='IE=9'>")
res := document.parentWindow.eval(script)
MsgBox, % Clipboard := res := StrReplace(res, """", "'")
Разработка AHK-скриптов:
e-mail dfiveg@mail.ru
Telegram jollycoder

3

Re: AKH: Сортировка массива.

Подозреваю, что вы скажете, что отсортировано неправильно.

Разработка AHK-скриптов:
e-mail dfiveg@mail.ru
Telegram jollycoder

4

Re: AKH: Сортировка массива.

Есть какие-то другие способы, без использования JS?

Win10: LTSC (21H2); AHK: ANSI (v1.1.36.02)

5

Re: AKH: Сортировка массива.

Так это же JSON, какие могут быть ещё способы?

Разработка AHK-скриптов:
e-mail dfiveg@mail.ru
Telegram jollycoder

6

Re: AKH: Сортировка массива.

Это был AHK массив, чтобы его вам для теста дать пришлось из него json сделать.

Win10: LTSC (21H2); AHK: ANSI (v1.1.36.02)

7 (изменено: teadrinker, 2019-03-22 17:20:14)

Re: AKH: Сортировка массива.

Называется левой рукой чесать правое ухо. Напишите в виде AHK массива. Ещё не очень понятно, как вы хотите воспринимать нужные ключи, как строки, или как числа? Это будут две разные сортировки. Если как числа, то зачем их значения в кавычках?

Разработка AHK-скриптов:
e-mail dfiveg@mail.ru
Telegram jollycoder

8

Re: AKH: Сортировка массива.

В массив собирается информация из диалога, его я перевел в JSON строку и предоставил вам.
Хотелось бы уникальную сортировку и для строк и для чисел, когда-то давно я нашел функцию "SortArray2D" и был рад, проверял и вроде как работало все как нужно, но вот когда реально необходимо было использовать, заметил вот такую вот фигню.. Меняются местами только "rankNum", остальные значения не меняются.

Win10: LTSC (21H2); AHK: ANSI (v1.1.36.02)

9

Re: AKH: Сортировка массива.

Преобразовывайте в строку ahk массив и сортируйте командой sort.

10

Re: AKH: Сортировка массива.

Можно какой-то пример?

Win10: LTSC (21H2); AHK: ANSI (v1.1.36.02)

11

Re: AKH: Сортировка массива.

Phoenixxx_Czar пишет:

В массив собирается информация из диалога, его я перевел в JSON строку и предоставил вам.

Так результат-то в каком виде нужен? В виде JSON или в виде AHK-массива?

Разработка AHK-скриптов:
e-mail dfiveg@mail.ru
Telegram jollycoder

12

Re: AKH: Сортировка массива.

AHK массива.

Win10: LTSC (21H2); AHK: ANSI (v1.1.36.02)

13 (изменено: teadrinker, 2019-03-22 20:02:31)

Re: AKH: Сортировка массива.

Я так и не понял, зачем нужно было в JSON переводить.

arr := [ {id: 43, isAFK: 1, nick: "Thiago_Montesdeoca", rankNum:  2}
       , {id: 40, isAFK: 0, nick: "kukumba"           , rankNum: 10}
       , {id:  5, isAFK: 1, nick: "blackboss"         , rankNum:  3} ]
key := "rankNum"

str := "", d := Chr(1)
for k, v in arr
   str .= (str = "" ? "" : d) . v[key] . "~" . k

Sort, str, % "D" . d
newArr := []
Loop, parse, str, % d
   newArr.Push(arr[ RegExReplace(A_LoopField, ".+~") ])

for k, v in newArr
   MsgBox, % v.nick

Это строчная сортировка. Для числовой добавьте N к опциям Sort.

Разработка AHK-скриптов:
e-mail dfiveg@mail.ru
Telegram jollycoder

14

Re: AKH: Сортировка массива.

Phoenixxx_Czar пишет:

Можно какой-то пример?

Готового примера нет, а писать лень.

15

Re: AKH: Сортировка массива.

teadrinker, а можно как-то обратную сортировку? (DESC)

Win10: LTSC (21H2); AHK: ANSI (v1.1.36.02)

16

Re: AKH: Сортировка массива.

Так смотрите хелп по Sort, там всё есть.

Разработка AHK-скриптов:
e-mail dfiveg@mail.ru
Telegram jollycoder

17

Re: AKH: Сортировка массива.

Что-то не получается у меня добавить "R", как и куда правильно ее добавить?
Пробовал и с пробелом и без, не дало результатов.

Sort, str, % "D" .d "R"
Sort, str, % "D" .d " R"
Sort, str, % "RD" .d
Sort, str, % "R D" .d
Win10: LTSC (21H2); AHK: ANSI (v1.1.36.02)

18 (изменено: teadrinker, 2019-03-22 20:46:31)

Re: AKH: Сортировка массива.

Sort, str, % "RD" . d

После точки пробел нужен. Или по-другому:

Sort, str, RD%d%
Разработка AHK-скриптов:
e-mail dfiveg@mail.ru
Telegram jollycoder

19

Re: AKH: Сортировка массива.

Где можно прочитать про точку? Не раз замечал ее присутствие, но думал это проделки PHP .

Win10: LTSC (21H2); AHK: ANSI (v1.1.36.02)

20

Re: AKH: Сортировка массива.

Здесь.

Разработка AHK-скриптов:
e-mail dfiveg@mail.ru
Telegram jollycoder

21

Re: AKH: Сортировка массива.

Вот так корректнее:

arr := [ {id: 43, isAFK: 1, nick: "Thiago_Montesdeoca", rankNum:  2}
       , {id: 40, isAFK: 0, nick: "kukumba"           , rankNum: 10}
       , {id:  5, isAFK: 1, nick: "blackboss"         , rankNum:  3} ]
key := "rankNum"

str := "", d1 := Chr(1), d2 := Chr(2)
for k, v in arr
   str .= (str = "" ? "" : d1) . v[key] . d2 . k

Sort, str, % "D" . d1
newArr := []
Loop, parse, str, % d1
   newArr.Push(arr[ RegExReplace(A_LoopField, ".+" . d2) ])

for k, v in newArr
   MsgBox, % v.nick
Разработка AHK-скриптов:
e-mail dfiveg@mail.ru
Telegram jollycoder

22

Re: AKH: Сортировка массива.

А что насчет простого массива?

array := [13, 4, 1, 58, 25]

Я находил код, но он слишком громоздкий и изменял основной массив (что-то по типу byRef).

SortArray(Array, Order := "A")
{
	;Order A: Ascending, D: Descending, R: Reverse
	MaxIndex := ObjMaxIndex(Array)
	If (Order == "R")
	{
		count := 0
		Loop, % MaxIndex
			ObjInsert(Array, ObjRemove(Array, MaxIndex - count++))
		Return
	}
	Partitions := "|" ObjMinIndex(Array) "," MaxIndex
	Loop
	{
		comma := InStr(this_partition := SubStr(Partitions, InStr(Partitions, "|", False, 0)+1), ",")
		spos := pivot := SubStr(this_partition, 1, comma-1) , epos := SubStr(this_partition, comma+1)
		if (Order == "A")
		{
			Loop, % epos - spos
			{
				if (Array[pivot] > Array[A_Index+spos])
					ObjInsert(Array, pivot++, ObjRemove(Array, A_Index+spos))
			}
		}
		else
		{
			Loop, % epos - spos
			{
				if (Array[pivot] < Array[A_Index+spos])
					ObjInsert(Array, pivot++, ObjRemove(Array, A_Index+spos))
			}
		}
		Partitions := SubStr(Partitions, 1, InStr(Partitions, "|", False, 0)-1)
		if (pivot - spos) > 1    ;if more than one elements
			Partitions .= "|" spos "," pivot-1        ;the left partition
		if (epos - pivot) > 1    ;if more than one elements
			Partitions .= "|" pivot+1 "," epos        ;the right partition
	}
	Until !Partitions
}
Win10: LTSC (21H2); AHK: ANSI (v1.1.36.02)

23

Re: AKH: Сортировка массива.

Так а в чём трудность прменить тот же принцип для более простого случая?

Разработка AHK-скриптов:
e-mail dfiveg@mail.ru
Telegram jollycoder

24

Re: AKH: Сортировка массива.

Не думал что он подойдет, то есть просто заменить "v[key]" на "v" и дело в шляпе?

Win10: LTSC (21H2); AHK: ANSI (v1.1.36.02)

25

Re: AKH: Сортировка массива.

Что-то типа этого вышло в итоге:

sortArray(array, key := "", desc := 1, string := 0)
{
	str := "", d1 := Chr(1), d2 := Chr(2)
	for k, v in array
		str .= (str = "" ? "" : d1) . (key ? v[key] : v) . d2 . k

	Sort, str, % (desc ? "R" : "") (string ? "" : "N") "D" . d1
	newArr := []
	Loop, parse, str, % d1
		newArr.Push(array[ RegExReplace(A_LoopField, ".+" . d2) ])
	return newArr
}
Win10: LTSC (21H2); AHK: ANSI (v1.1.36.02)

26

Re: AKH: Сортировка массива.

Ну вот, оказывается всё не так уж сложно.

Разработка AHK-скриптов:
e-mail dfiveg@mail.ru
Telegram jollycoder