Reversing lines in a text variable Topic is solved

Get help with using AutoHotkey (v1.1 and older) and its commands and hotkeys
paik1002
Posts: 355
Joined: 28 Nov 2015, 02:45

Reversing lines in a text variable

21 Sep 2018, 06:12

What is the fastest way to reverse the lines in a large-sized variable of text?

For example, if the text variable has:
apple
banana
orange
blackberry
coconut

Reversing the line order will yield:
coconut
blackberry
orange
banana
apple

Your kind help would be appreciated.
art
Posts: 22
Joined: 01 Jan 2014, 05:56

Re: Reversing lines in a text variable

21 Sep 2018, 06:51

Code: Select all

v=
(
apple
banana
orange
blackberry
coconut
)

s:=StringReverse(v, "`n")
MsgBox,4096,StringReverse, %s%
exitapp

;================================================================================
StringReverse(str, Separator="", OmitChars="") {
   Loop,Parse,% StrReplace(str,Separator,(BS:=chr(8))),%BS%,%OmitChars%
      i := A_LoopField (a_index=1 ? "" : BS i)
   Return StrReplace(i, BS, Separator)
}  ; A|B|CD --> CD|B|A
KnowNothing

Re: Reversing lines in a text variable

21 Sep 2018, 06:59

not a nice solution but this is what i know, if your line has a number in front of each u can use the sort option

Code: Select all

RTEXT = 
(
apple
banana
orange
blackberry
coconut
)
FileAppend, %RTEXT%, FileOfItems.txt
loop, parse, RTEXT, `n
	NLINES := A_Index
loop, %NLINES%
{
FileReadLine, ToReverse, FileOfItems.txt, %NLINES%
NewReverseData .= ToReverse "`n"
NLINES--
}
msgbox, % NewReverseData
FileDelete, FileOfItems.txt
ExitApp
	
swagfag
Posts: 6222
Joined: 11 Jan 2017, 17:59

Re: Reversing lines in a text variable  Topic is solved

21 Sep 2018, 07:17

Code: Select all

fruits =
(
apple
banana
orange
blackberry
coconut
)

Loop Parse, fruits, `n, `r
	result := A_LoopField "`n" result

MsgBox % result
paik1002
Posts: 355
Joined: 28 Nov 2015, 02:45

Re: Reversing lines in a text variable

22 Sep 2018, 02:45

Thanks to all for pitching in!
Guest

Re: Reversing lines in a text variable

28 Sep 2018, 01:51

Depending on other needs TF may be useful as it has https://github.com/hi5/TF#TF_ReverseLines function (may be slow on very large files and variables but posting here for reference)
SundayProgrammer
Posts: 143
Joined: 25 Dec 2020, 12:26

Re: Reversing lines in a text variable

06 Jul 2021, 10:51

not the fastest, but its speed is probably good enough for most of the tasks.

Code: Select all

bytes_per_char := A_IsUnicode ? 2 : 1
varsetcapacity(oritext, 5000000 * bytes_per_char)
loop, 100000
	oritext .= "line " a_index " some text is better than none at all`n"
oritext .= mod(a_tickcount, 2) ? "(random last line test)" : ""

text := oritext
tooltip, stopwatch now
timebegin := a_tickcount
mReverseByLine(text)
lapse := a_tickcount - timebegin
tooltip
msgbox % "method one`n`ntime spent: " lapse " ms`ntotal length: " strlen(text) " chars`n" substr(text, 1, 1000) "..."

mReverseByLine(ByRef text, delimiter := "`n") {
	text := text (SubStr(text, 0) = delimiter ? "" : delimiter), address := &text, srclen := StrLen(text), prolen := 0, bytes_per_char := A_IsUnicode ? 2 : 1
	Loop, Parse, text, % delimiter
		len := StrLen(A_LoopField), StrPut(A_LoopField delimiter, address + (srclen - prolen - len - 1) * bytes_per_char, len + 1), prolen += len + 1
}

text := oritext
tooltip, stopwatch now
timebegin := a_tickcount
sReverseByLine(text)
lapse := a_tickcount - timebegin
tooltip
msgbox % "method two`n`ntime spent: " lapse " ms`ntotal length: " strlen(text) " chars`n" substr(text, 1, 1000) "..."

sReverseByLine(ByRef text, delimiter := "`n") {
	array := StrSplit(SubStr(text, 0) = delimiter ? SubStr(text, 1, StrLen(text) - 1) : text, delimiter), mi := array.MaxIndex()
	Loop, % mi
		If A_Index > 1
			text .= array[mi - A_Index + 1] delimiter
		Else text := array[mi] delimiter
}

text := oritext
tooltip, stopwatch now
timebegin := a_tickcount
Sort, text, F ReverseDirection
lapse := a_tickcount - timebegin
tooltip
msgbox % "method three`n`ntime spent: " lapse " ms`ntotal length: " strlen(text) " chars`n" substr(text, 1, 1000) "..."

ReverseDirection(a1, a2, offset)
{
    return offset  ; Offset is positive if a2 came after a1 in the original list; negative otherwise.
}
2021-7-7 edited: one more method is added.
after @flyingDman's post, i've added his (the sort method from autohotkey documentation) as the third one in the benchmark.
for @Chunjee, i don't know how to include yours. it will be nice if you can advise how. (better not the whole library but only the necessary extracts.) thanks.
Last edited by SundayProgrammer on 07 Jul 2021, 16:09, edited 1 time in total.
User avatar
Chunjee
Posts: 1417
Joined: 18 Apr 2014, 19:05
Contact:

Re: Reversing lines in a text variable

07 Jul 2021, 12:09

I use https://biga-ahk.github.io/biga.ahk/#/?id=reverse

This is more array centric however. For convince I've turned the final result back into a string:

Code: Select all

fruits =
(
apple
banana
orange
blackberry
coconut
)

fruitsArray := StrSplit(fruits, "`n")
fruitsArray := A.reverse(fruitsArray)
reversedFruitString := A.join(fruitsArray, "`n")
msgbox, % reversedFruitString
; =>
/* coconut
blackberry
orange
banana
apple 
*/
User avatar
flyingDman
Posts: 2817
Joined: 29 Sep 2013, 19:01

Re: Reversing lines in a text variable

07 Jul 2021, 13:08

From the help file (https://www.autohotkey.com/docs/commands/Sort.htm):

Code: Select all

fruits =
(
apple
banana
orange
blackberry
coconut
)

Sort, fruits, F ReverseDirection  ; Reverses the list
msgbox % fruits

ReverseDirection(a1, a2, offset)
	{
	return offset  				; Offset is positive if a2 came after a1 in the original list; negative otherwise.
	}	
14.3 & 1.3.7
swagfag
Posts: 6222
Joined: 11 Jan 2017, 17:59

Re: Reversing lines in a text variable

10 Jul 2021, 21:28

SundayProgrammer wrote:
06 Jul 2021, 10:51
for @Chunjee, i don't know how to include yours. it will be nice if you can advise how. (better not the whole library but only the necessary extracts.) thanks.
itd be pointless to bench it. since it doesnt preallocate, for strings requiring varsetcapacity(oritext, 5000000 * bytes_per_char) it would be extremely slow:

Code: Select all

	join(param_array,param_sepatator:=",") {
		if (!isObject(param_array) || isObject(param_sepatator)) {
			this._internal_ThrowException()
		}

		; prepare
		l_array := this.clone(param_array)

		; create
		for l_key, l_value in l_array {
			if (A_Index == 1) {
				l_string := "" l_value
				continue
			}
			l_string := l_string param_sepatator l_value
		}
		return l_string
	}
its not even certain it would finish in any sort of reasonable time

Return to “Ask for Help (v1)”

Who is online

Users browsing this forum: Draken, Google [Bot], MrDoge, Rohwedder and 241 guests