1

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

Голова не варит, или может забыл, в анк есть что то для сортировки массивов?
Нужно отсортировать массив по значению, чтобы он начинался с большего значения к меньшему

arr := [{value: 1}, {value: 3}, {value: 2}, {value: 2}]
результат
[{value: 3}, {value: 2}, {value: 2}, {value: 1}]
По вопросам возмездной помощи пишите на E-Mail: serzh82saratov@mail.ru Telegram: https://t.me/sergiol982
Win10x64 AhkSpy, Hotkey, ClockGui

2

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

Нету, только в строку переводить.

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

3 (изменено: serzh82saratov, 2024-08-24 14:01:56)

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

Эх, пришлось делать.

arr := [{value: 1}, {value: 3}, {value: 2}, {value: 2}]

MsgBox % PrintArray(arr,  "`n" )
MsgBox % PrintArray(SortDescending(arr, "value"), "`n")

PrintArray(arr, del = "") {
	for k, v in arr
		str .= del k ":" ((IsFunc(v) ? "__Function" : IsObject(v) ? PrintArray(v, del) : (v + 0 != "" ? v : """" v """")))", " 
	Return "{" RTrim(str, ", ") del "}"
}

SortDescending(arr, key, sort = "R N") {
	order := {}, res := [], str := ""
	for k, v in arr {
		str .= v[key] ","
	}  
	Sort str, U D, Z %sort%
	Loop, Parse, str, `, 
		order[A_LoopField] := A_Index  
	for k, v in arr {
		res.InsertAt(order[v[key]] + A_Index, v)
	} 
	Return res
}
По вопросам возмездной помощи пишите на E-Mail: serzh82saratov@mail.ru Telegram: https://t.me/sergiol982
Win10x64 AhkSpy, Hotkey, ClockGui

4

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

Помню, обсуждали эту тему тут когда-то.

arr := [{value: 1}, {value: 3}, {value: 2}, {value: 2}]
sorted := SortByKey(arr, "value", true)
MsgBox % PrintArray(sorted)

SortByKey(arr, key, reverse := false) {
    ArrMin := [], ArrMax := []
    Random, pivot, 1, arr.Count()
    for k, v in arr {
        if (k = pivot)
            continue

        array := (!reverse ? arr[k, key] < arr[pivot, key] : arr[k, key] > arr[pivot, key]) ? "ArrMin" : "ArrMax"
        %array%.Push(v)
    }
    for k, v in ["ArrMin", "ArrMax"]
       (%v%.Length() > 1 && %v% := SortByKey(%v%, key, reverse))

    ArrMin.Push(arr[pivot], ArrMax*)
    Return ArrMin
}

PrintArray(arr, del = "") {
	for k, v in arr
		str .= del k ":" ((IsFunc(v) ? "__Function" : IsObject(v) ? PrintArray(v, del) : (v + 0 != "" ? v : """" v """")))", " 
	Return "{" RTrim(str, ", ") del "}"
}

Здесь какой-то из продвинутых алгоритмов используется.

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

5

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

ChatGPT подсказал, что это QuickSort.

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

6

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

Не, тут я сам. А продвинутых сейчас уже читать не могу на отдыхе, расскажи в двух словах разницу.)

По вопросам возмездной помощи пишите на E-Mail: serzh82saratov@mail.ru Telegram: https://t.me/sergiol982
Win10x64 AhkSpy, Hotkey, ClockGui

7

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

Могу в одно слово: быстрее.

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

8

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

А в целом конечно пипец, как я раньше не замечал, на js сейчас больше, там оно пожалуйста.

По вопросам возмездной помощи пишите на E-Mail: serzh82saratov@mail.ru Telegram: https://t.me/sergiol982
Win10x64 AhkSpy, Hotkey, ClockGui

9

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

teadrinker пишет:

Могу в одно слово: быстрее.

Спасибо, учтём.)

По вопросам возмездной помощи пишите на E-Mail: serzh82saratov@mail.ru Telegram: https://t.me/sergiol982
Win10x64 AhkSpy, Hotkey, ClockGui

10

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

teadrinker пишет:

Здесь какой-то из продвинутых алгоритмов используется.

Да, тут чёто лютое. )

По вопросам возмездной помощи пишите на E-Mail: serzh82saratov@mail.ru Telegram: https://t.me/sergiol982
Win10x64 AhkSpy, Hotkey, ClockGui

11

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

Кто же автор?

По вопросам возмездной помощи пишите на E-Mail: serzh82saratov@mail.ru Telegram: https://t.me/sergiol982
Win10x64 AhkSpy, Hotkey, ClockGui

12

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

Не знаю, учёный какой-то наверно.

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

13

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

teadrinker пишет:

Могу в одно слово: быстрее.

А как ты это определил? По моим тестам мой в 2 раза быстрее.

По вопросам возмездной помощи пишите на E-Mail: serzh82saratov@mail.ru Telegram: https://t.me/sergiol982
Win10x64 AhkSpy, Hotkey, ClockGui

14 (изменено: serzh82saratov, 2024-08-25 09:31:00)

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

А нет, тот мой косячный, думаю этот верный, и он на 50% быстрее. И опций по сортировке больше.

arr := [{value: 1}, {value: 32}, {value: 3}, {value: 2}, {value: 32}, {value: 32}, {value: 2}]
 
sorted := SortDescending(arr, "value")  
MsgBox % PrintArray(sorted,  "`n" )

SortDescending(arr, key, sort = "R N", del = "|") {
	res := [], ex := {}, str := "" 
	for k, v in arr {
		str .= v[key] del
		If !ex[v[key]]
			ex[v[key]] := []
		ex[v[key]].push(k)
	}
	Sort str, U D%del% Z %sort%
	Loop, Parse, str, %del%
	{
		for k, v in ex[A_LoopField]  
			res.push(arr[v])
	} 
	Return res 
}
По вопросам возмездной помощи пишите на E-Mail: serzh82saratov@mail.ru Telegram: https://t.me/sergiol982
Win10x64 AhkSpy, Hotkey, ClockGui

15

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

Да, проверил, действительно быстрее. Значит, встроенный Sort не перебить.

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

16 (изменено: serzh82saratov, 2024-08-26 18:50:30)

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

Думаю Sort  не причём, код перемудрёный не значит хорошо.)

Только по числам можно в 2 прохода, Sort в том варианте только для поддержки строк, хотя может что то тут упустил с числами.
У цикла есть встроенное свойство перебирать от меньшего к большему. Этот в 3 раза быстрее, кол-во итераций достаточно длинна * 2, а там 2 цикла с рекурсией которую поди пойми сколько раз она их запускает, на длинных массивах думаю там печальнее становится.


arr := [{value: 1}, {value: 32}, {value: 3}, {value: 2}, {value: 32}, {value: 32}, {value: 2}]

sorted := SortDescending(arr, "value", 1) 
MsgBox % PrintArray(sorted,  "`n" )

SortDescending(arr, key, reverse := false) {
	res := [], ex := [] 
	for k, v in arr { 
		If !ex[v[key]]
			ex[v[key]] := []
		ex[v[key]].push(k)
	}
	for k, v in ex { 
		for k2, v2 in ex[k]
			reverse ? res.insertat(1, arr[ex[k][k2]]) : res.push(arr[ex[k][k2]]) 
	} 
	Return res 
}
PrintArray(arr, del = "") {
	for k, v in arr
		str .= del k ":" ((IsFunc(v) ? "__Function" : IsObject(v) ? PrintArray(v, del) : (v + 0 != "" ? v : """" v """")))", " 
	Return "{" RTrim(str, ", ") del "}"
}
По вопросам возмездной помощи пишите на E-Mail: serzh82saratov@mail.ru Telegram: https://t.me/sergiol982
Win10x64 AhkSpy, Hotkey, ClockGui

17

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

Я замерил, Sort гораздо быстрее работает.
А код от teadrinkerа может просто дать сбой:

arr := []
loop 1000
   arr.push({value: 1})
sorted := SortByKey(arr, "value")

SortByKey(arr, key, reverse := false) {
    ArrMin := [], ArrMax := []
    Random, pivot, 1, arr.Count()
    for k, v in arr {
        if (k = pivot)
            continue

        array := (!reverse ? arr[k, key] < arr[pivot, key] : arr[k, key] > arr[pivot, key]) ? "ArrMin" : "ArrMax"
        %array%.Push(v)
    }
    for k, v in ["ArrMin", "ArrMax"]
       (%v%.Length() > 1 && %v% := SortByKey(%v%, key, reverse))

    ArrMin.Push(arr[pivot], ArrMax*)
    Return ArrMin
}

18

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

А так:

SetBatchLines, -1

arr := []
Loop 100000 {
    Random, rand
    arr.Push({value: rand})
}
start := A_TickCount
res1 := SortByKey(arr, "value", true)
end1 := A_TickCount
res2 := SortDescending(arr, "value")
end2 := A_TickCount

MsgBox % A_Clipboard := end1 - start . "`n" . end2 - end1 . "`n`n" . PrintArray(res1) . "`n`n" . PrintArray(res2)

SortDescending(arr, key, sort = "R N", del = "|") {
	res := [], ex := {}, str := "" 
	for k, v in arr {
		str .= v[key] del
		If !ex[v[key]]
			ex[v[key]] := []
		ex[v[key]].push(k)
	}
	Sort str, U D%del% Z %sort%
	Loop, Parse, str, %del%
	{
		for k, v in ex[A_LoopField]  
			res.push(arr[v])
	} 
	Return res 
}

SortByKey(arr, key, reverse := false) {
    stack := []
    stack.Push([1, arr.Length()])

    while (stack.Length() > 0) {
        low := stack.Pop()
        high := low[2]
        low := low[1]

        while (high - low > 10) {
            pivotIndex := MedianOfThree(arr, low, high, key, reverse)
            pivotIndex := Partition(arr, low, high, pivotIndex, key, reverse)

            if (pivotIndex - low < high - pivotIndex) {
                stack.Push([pivotIndex + 1, high])
                high := pivotIndex - 1
            } else {
                stack.Push([low, pivotIndex - 1])
                low := pivotIndex + 1
            }
        }
        InsertionSort(arr, low, high, key, reverse)
    }

    return arr
}

MedianOfThree(arr, low, high, key, reverse) {
    mid := low + (high - low) // 2
    if reverse {
        if (arr[low, key] < arr[mid, key])
            Swap(arr, low, mid)
        if (arr[mid, key] < arr[high, key])
            Swap(arr, mid, high)
        if (arr[low, key] < arr[mid, key])
            Swap(arr, low, mid)
    } else {
        if (arr[low, key] > arr[mid, key])
            Swap(arr, low, mid)
        if (arr[mid, key] > arr[high, key])
            Swap(arr, mid, high)
        if (arr[low, key] > arr[mid, key])
            Swap(arr, low, mid)
    }
    return mid
}

Partition(arr, low, high, pivotIndex, key, reverse) {
    pivot := arr[pivotIndex, key]
    Swap(arr, pivotIndex, high)

    i := low - 1

    Loop, % high - low {
        j := A_Index + low - 1
        compare := !reverse ? arr[j, key] < pivot : arr[j, key] > pivot
        if compare {
            i++
            Swap(arr, i, j)
        }
    }

    Swap(arr, i + 1, high)
    return i + 1
}

InsertionSort(arr, low, high, key, reverse) {
    Loop, % high - low {
        i := A_Index + low
        j := i
        while (j > low) {
            compare := !reverse ? arr[j, key] < arr[j-1, key] : arr[j, key] > arr[j-1, key]
            if compare
                Swap(arr, j, j-1)
            else
                break
            j--
        }
    }
}

Swap(arr, i, j) {
    temp := arr[i]
    arr[i] := arr[j]
    arr[j] := temp
}

PrintArray(arr, del = "") {
	for k, v in arr
		str .= del k ":" ((IsFunc(v) ? "__Function" : IsObject(v) ? PrintArray(v, del) : (v + 0 != "" ? v : """" v """")))", " 
	Return "{" RTrim(str, ", ") del "}"
}
Разработка AHK-скриптов:
e-mail dfiveg@mail.ru
Telegram jollycoder

19

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

Тут уже совсем другой код, опроверг сам себя что Sort не перебить.
4000 против 5500 с Sort, и против 20000 без Sort, не ожидал.

Тут я так понял жпт постарался.

По вопросам возмездной помощи пишите на E-Mail: serzh82saratov@mail.ru Telegram: https://t.me/sergiol982
Win10x64 AhkSpy, Hotkey, ClockGui

20

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

Но на 50000 ключей с Sort быстрее, на 60000 примерно вровень.

По вопросам возмездной помощи пишите на E-Mail: serzh82saratov@mail.ru Telegram: https://t.me/sergiol982
Win10x64 AhkSpy, Hotkey, ClockGui

21

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

Чем больше массив, тем больше проявляется польза алгоритма. Кстати, чтобы ускорить использование Sort, нужно добавить VarSetCapacity.

serzh82saratov пишет:

Тут уже совсем другой код

Это всё ещё QuickSort, который, насколько я помню, используется и в Sort. Но там есть разные модификации.

serzh82saratov пишет:

Тут я так понял жпт постарался.

Не, это был Клод.

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

22

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

teadrinker пишет:

Кстати, чтобы ускорить использование Sort, нужно добавить VarSetCapacity

Пример можно.


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

По вопросам возмездной помощи пишите на E-Mail: serzh82saratov@mail.ru Telegram: https://t.me/sergiol982
Win10x64 AhkSpy, Hotkey, ClockGui

23

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

А с такими данными:

Loop 10000 {
    arr.Push({value: 1})
}

в 1890 раз "Клод" тормознутее.

24 (изменено: serzh82saratov, 2024-08-27 21:04:45)

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

Эх, ё моё блин... Ху из "Клод"? Моне...

По вопросам возмездной помощи пишите на E-Mail: serzh82saratov@mail.ru Telegram: https://t.me/sergiol982
Win10x64 AhkSpy, Hotkey, ClockGui

25

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

Malcev
Это ты понял код, чтобы понять как сделать такой тест?

По вопросам возмездной помощи пишите на E-Mail: serzh82saratov@mail.ru Telegram: https://t.me/sergiol982
Win10x64 AhkSpy, Hotkey, ClockGui

26

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

Не, просто решил попробовать проверить с одинаковыми числами.
https://claude.ai/

27

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

serzh82saratov пишет:

Пример можно

    VarSetCapacity(str, ...) ; здесь прикинуть, сколько может потребоваться
	for k, v in arr {
		str .= v[key] del
		If !ex[v[key]]
			ex[v[key]] := []
		ex[v[key]].push(k)
	}
	Sort str, U D%del% Z %sort%
Разработка AHK-скриптов:
e-mail dfiveg@mail.ru
Telegram jollycoder

28 (изменено: serzh82saratov, 2024-08-28 12:44:01)

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

teadrinker пишет:

Кстати, чтобы ускорить использование Sort, нужно добавить VarSetCapacity.

А с чем это связано, перед тем как попасть в Sort она ведь и так имеет нужный размер, а чтобы прикинуть размер, надо ещё раз массив перебрать. То есть массив перебирать и вычислять быстрее, чем при каждом добавлении в строку расширять её память. Если так то это не касается именно Sort, а это в общем так. Ну то есть не ускорить Sort, а ускорить формирование строки.

По вопросам возмездной помощи пишите на E-Mail: serzh82saratov@mail.ru Telegram: https://t.me/sergiol982
Win10x64 AhkSpy, Hotkey, ClockGui

29

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

Да, формирование строки. Я имел в виду ускорить пример с использованием Sort.

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

30

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

Ну, сильно оно не ускорит.
res.SetCapacity() побольше ускорения даст.

31

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

Почему не ускорит? У меня раза в полтора ускоряет на большом массиве.

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

32

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

SetBatchLines, -1

arr := []
arr.SetCapacity(100000000) 
Loop 100000 {
    Random, rand
    arr.Push({value: rand})
}

a := A_TickCount
SortDescending(arr, "value")
msgbox % A_TickCount - a

a := A_TickCount
SortDescending1(arr, "value")
msgbox % A_TickCount - a

a := A_TickCount
SortDescending2(arr, "value")
msgbox % A_TickCount - a


SortDescending(arr, key, sort = "R N", del = "|") {
	res := [], ex := {}, str := "" 
	for k, v in arr {
		str .= v[key] del
		If !ex[v[key]]
			ex[v[key]] := []
		ex[v[key]].push(k)
	}
	Sort str, U D%del% Z %sort%
	Loop, Parse, str, %del%
	{
		for k, v in ex[A_LoopField]  
			res.push(arr[v])
	} 
	Return res 
}


SortDescending1(arr, key, sort = "R N", del = "|") {
	res := [], ex := {}, str := "" 
; res.SetCapacity(100000000) 
 VarSetCapacity(str, 100000000)
	for k, v in arr {
		str .= v[key] del
		If !ex[v[key]]
			ex[v[key]] := []
		ex[v[key]].push(k)
	}
	Sort str, U D%del% Z %sort%
	Loop, Parse, str, %del%
	{
		for k, v in ex[A_LoopField]  
			res.push(arr[v])
	} 
	Return res 
}

SortDescending2(arr, key, sort = "R N", del = "|") {
	res := [], ex := {}, str := "" 
 res.SetCapacity(100000000) 
; VarSetCapacity(str, 100000000)
	for k, v in arr {
		str .= v[key] del
		If !ex[v[key]]
			ex[v[key]] := []
		ex[v[key]].push(k)
	}
	Sort str, U D%del% Z %sort%
	Loop, Parse, str, %del%
	{
		for k, v in ex[A_LoopField]  
			res.push(arr[v])
	} 
	Return res 
}

33

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

Да, странно, у меня вчера вроде показывало прирост. Но и от SetCapacity результат не особо значительный, у меня:
8300 - 8500
8100 - 8300
7600 - 7900

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