Easy Quesion about Array Topic is solved

Get help with using AutoHotkey (v1.1 and older) and its commands and hotkeys
User avatar
masheen
Posts: 295
Joined: 06 Dec 2016, 14:10

Easy Quesion about Array

12 Sep 2017, 15:35

Pid[1] := 1234
Pid[2] := 5678

How to delete array element by value? like this Pid.Remove(5678)
Helgef
Posts: 4709
Joined: 17 Jul 2016, 01:02
Contact:

Re: Easy Quesion about Array

12 Sep 2017, 16:33

Maybe like this

Code: Select all

Pid:=[]
Pid[1] := 1234
Pid[2] := 5678

removeValue(pid,5678)
msgbox % Pid[2]

removeValue(arr,val){
	t:=[]
	for k, v in arr
		if (v==val)
			t.push(k)
	for k, v in t
		arr.delete(v)
}
teadrinker
Posts: 4309
Joined: 29 Mar 2015, 09:41
Contact:

Re: Easy Quesion about Array  Topic is solved

12 Sep 2017, 17:16

Helgef wrote:Maybe like this
No :)

Code: Select all

Pid := [123, 456, 789]

RemoveValue(pid, 456)
MsgBox, % Pid[1] . "`n" . Pid[2] . "`n" . Pid[3]

RemoveValue(arr, val)  {
   for k, v in arr
      if (v = val)
         Return arr, arr.Delete(k)
}
User avatar
jeeswg
Posts: 6902
Joined: 19 Dec 2016, 01:58
Location: UK

Re: Easy Quesion about Array

12 Sep 2017, 22:56

For something like this I might use an associative array instead of a linear array, like so:

Code: Select all

q::
oPID := {1114:"",2224:""}
MsgBox, % oPID.HasKey(1114)
MsgBox, % oPID.HasKey(3334)
oPID[3334] := "" ;this adds the key to the array
oPID.Delete(2224)
vOutput := ""
for vKey, vValue in oPID
	vOutput .= vKey " " vValue "`r`n"
oPID := ""
MsgBox, % vOutput
return
For the linear array approach:

Code: Select all

q::
oPID := [1234,5678,1234,5678,1234,5678,1234,5678,1234,5678]
Loop, % vLen := oPID.Length()
{
	if (oPID[vLen] = 5678)
		oPID.RemoveAt(vLen)
		vLen--
}
for vKey, vValue in oPID
	vOutput .= vKey " " vValue "`r`n"
oPID := ""
MsgBox, % vOutput
return
Note:
- both teadrinker's and Helgef's functions clear rather than delete keys (which may be desirable)
- teadrinker's function only clears the first match (which may be desirable)
- teadrinker's function uses multiple parameters on a return line which is a potential issue re. AHK v2 forwards compatibility
Last edited by jeeswg on 13 Sep 2017, 01:56, edited 1 time in total.
homepage | tutorials | wish list | fun threads | donate
WARNING: copy your posts/messages before hitting Submit as you may lose them due to CAPTCHA
Helgef
Posts: 4709
Joined: 17 Jul 2016, 01:02
Contact:

Re: Easy Quesion about Array

13 Sep 2017, 01:40

jeeswg wrote:Linear array approach
Your code in function. ;)

Code: Select all

removeVal(arr,val){
	Loop % vLen := arr.Length()
		if (arr[vLen--] = val)
			arr.RemoveAt(vLen+1)
}
jeeswg wrote:Note:
1 and 2. There was no specification.
3, it doesn't work in v2, returning the array is ofc superfluous.

@op. If there are string values, note the difference between v = val and v == val, and pick your preference.

cheers.
teadrinker
Posts: 4309
Joined: 29 Mar 2015, 09:41
Contact:

Re: Easy Quesion about Array

13 Sep 2017, 07:52

jeeswg wrote:both teadrinker's and Helgef's functions clear rather than delete keys (which may be desirable)
No, both namely delete keys, yours remove. That may be undesirable, if I expect to see other keys in their old places.
Your approach is good, but nobody said that an array should be linear. :)
User avatar
jeeswg
Posts: 6902
Joined: 19 Dec 2016, 01:58
Location: UK

Re: Easy Quesion about Array

13 Sep 2017, 08:07

Ah yes, deleting keys in associative arrays, the problem being that you can't loop an associative array backwards. This script records which keys to delete, then deletes them afterwards.

To handle an associative array:

Code: Select all

q::
oArray := Object(StrSplit("a,1,b,2,c,3,d,1,e,2,f,3,g,1,h,2,i,3", ",")*)

;list keys
vOutput := ""
for vKey, vValue in oArray
	vOutput .= vKey " " vValue "`r`n"
MsgBox, % vOutput

;remove keys where the value is 2
oRemove := []
for vKey, vValue in oArray
	if (vValue = 2)
		oRemove.Push(vKey)
Loop, % vIndex := oRemove.Length()
	oArray.Delete(oRemove[vIndex--])

;list keys
vOutput := ""
for vKey, vValue in oArray
	vOutput .= vKey " " vValue "`r`n"
MsgBox, % vOutput

oArray := oRemove := ""
return
homepage | tutorials | wish list | fun threads | donate
WARNING: copy your posts/messages before hitting Submit as you may lose them due to CAPTCHA
Helgef
Posts: 4709
Joined: 17 Jul 2016, 01:02
Contact:

Re: Easy Quesion about Array

13 Sep 2017, 11:44

jeeswg wrote:This script records which keys to delete, then deletes them afterwards.
Nifty :thumbup: :angel:
teadrinker
Posts: 4309
Joined: 29 Mar 2015, 09:41
Contact:

Re: Easy Quesion about Array

13 Sep 2017, 12:21

jeeswg, this code

Code: Select all

oRemove := []
for vKey, vValue in oArray
	if (vValue = 2)
		oRemove.Push(vKey)
Loop, % vIndex := oRemove.Length()
	oArray.Delete(oRemove[vIndex--])
you may fearlessly replace with this:

Code: Select all

for vKey, vValue in oArray
	if (vValue = 2)
		oArray.Delete(vKey)
Helgef
Posts: 4709
Joined: 17 Jul 2016, 01:02
Contact:

Re: Easy Quesion about Array

13 Sep 2017, 12:26

teadrinker wrote:jeeswg, this code

Code: Select all

oRemove := []
for vKey, vValue in oArray
	if (vValue = 2)
		oRemove.Push(vKey)
Loop, % vIndex := oRemove.Length()
	oArray.Delete(oRemove[vIndex--])
you may fearlessly replace with this:

Code: Select all

for vKey, vValue in oArray
	if (vValue = 2)
		oArray.Delete(vKey)
No :)
teadrinker
Posts: 4309
Joined: 29 Mar 2015, 09:41
Contact:

Re: Easy Quesion about Array

13 Sep 2017, 12:32

Why?

Code: Select all

oArray := [1, 2, 1, 2, 1, 2]

;list keys
vOutput := ""
for vKey, vValue in oArray
   vOutput .= vKey " " vValue "`r`n"
MsgBox, % vOutput

;remove keys where the value is 2
for vKey, vValue in oArray
   if (vValue = 2)
      oArray.Delete(vKey)

;list keys
vOutput := ""
for vKey, vValue in oArray
   vOutput .= vKey " " vValue "`r`n"
MsgBox, % vOutput

oArray := oRemove := ""
return
Helgef
Posts: 4709
Joined: 17 Jul 2016, 01:02
Contact:

Re: Easy Quesion about Array

13 Sep 2017, 12:34

You'll get there eventually. Edit: Forgot the smile: :angel:
teadrinker
Posts: 4309
Joined: 29 Mar 2015, 09:41
Contact:

Re: Easy Quesion about Array

13 Sep 2017, 12:37

I'm not sure. :) May be, an example?
User avatar
jeeswg
Posts: 6902
Joined: 19 Dec 2016, 01:58
Location: UK

Re: Easy Quesion about Array

13 Sep 2017, 12:58

Try:

Code: Select all

oArray := [2, 2, 2, 2, 2, 2]
homepage | tutorials | wish list | fun threads | donate
WARNING: copy your posts/messages before hitting Submit as you may lose them due to CAPTCHA
teadrinker
Posts: 4309
Joined: 29 Mar 2015, 09:41
Contact:

Re: Easy Quesion about Array

13 Sep 2017, 13:18

Yes, you were right, for me it's unexpected behavior. Then this way:

Code: Select all

for vKey, vValue in oArray.Clone()
	if (vValue = 2)
		oArray.Delete(vKey)
Helgef
Posts: 4709
Joined: 17 Jul 2016, 01:02
Contact:

Re: Easy Quesion about Array

13 Sep 2017, 15:43

teadrinker wrote:for me it's unexpected behavior.
for loop remarks wrote:Existing key-value pairs may be modified during the loop, but inserting or removing keys may cause some items to be skipped or enumerated multiple times.
It is not something unique for ahk. Easy to miss though, I sure have at times and probably will again. :lol:
teadrinker wrote: Then this way:

Code: Select all

for vKey, vValue in oArray.Clone()
	if (vValue = 2)
		oArray.Delete(vKey)
Nice and short :thumbup: I'd worry slightly about cloning large arrays, but probably you will not go through large arrays looking for values to delete :think: Anyways, always fun to see all ideas. Cheers.
teadrinker
Posts: 4309
Joined: 29 Mar 2015, 09:41
Contact:

Re: Easy Quesion about Array

13 Sep 2017, 15:57

Helgef wrote:
for loop remarks wrote:Existing key-value pairs may be modified during the loop, but inserting or removing keys may cause some items to be skipped or enumerated multiple times.
Thanks, I'll try to keep it on mind. Cheers.
User avatar
jeeswg
Posts: 6902
Joined: 19 Dec 2016, 01:58
Location: UK

Re: Easy Quesion about Array

16 Sep 2017, 15:21

@teadrinker: Nice code re. cloning and deleting, it turned out simpler than I expected. Yes, there are many things to consider, I did think of cloning and deleting, and also, copying the keys you want to keep to a new array. One reason not to clone might be, if there keys with subkeys etcetera. I can't remember what exactly the possible reasons against cloning were, and/or if someone came up with a special clone function ...

One thing I was curious about was what would happen if you deleted every key, either starting from the front or the back. The differences in speed are very pronounced:

Code: Select all

q:: ;benchmark tests: delete keys from object forwards/backwards
vOutput := ""
vNum := 200000

oArray := {}
Loop, % vNum
	oArray.Push("abcdefghij")
vTickCount1 := A_TickCount
Loop, % vIndex := oArray.Length()
	oArray.Delete(oArray[vIndex--])
vTickCount2 := A_TickCount
vOutput .= (vTickCount2-vTickCount1) "`r`n"

oArray := {}
Loop, % vNum
	oArray.Push("abcdefghij")
vTickCount1 := A_TickCount
Loop, % oArray.Length()
	oArray.Delete(A_Index)
vTickCount2 := A_TickCount
vOutput .= (vTickCount2-vTickCount1) "`r`n"

oArray := ""
MsgBox, % vOutput
return

;100000 keys:
;47
;4430

;200000 keys:
;94
;20873
So in short, deleting the last key has almost no cost, and deleting the first key has a big cost. However, if you delete *some* keys, then there will be various keys after each key that you delete that will need to be reshuffled. Although I would suppose that deleting some keys, won't be as bad as the probable worst-case scenario of deleting every key starting from the front.
homepage | tutorials | wish list | fun threads | donate
WARNING: copy your posts/messages before hitting Submit as you may lose them due to CAPTCHA
Helgef
Posts: 4709
Joined: 17 Jul 2016, 01:02
Contact:

Re: Easy Quesion about Array

16 Sep 2017, 16:29

I can't remember what exactly the possible reasons against cloning were
The array might contain huge strings. You will copy them and then discard them after the loop. It could be very wasteful.
teadrinker
Posts: 4309
Joined: 29 Mar 2015, 09:41
Contact:

Re: Easy Quesion about Array

17 Sep 2017, 11:07

@jeeswg
deleting the last key has almost no cost, and deleting the first key has a big cost.
It's really an interesting observation. Notice, that the code

Code: Select all

oArray.Delete(oArray[vIndex--])
is incorrect, you needed

Code: Select all

oArray.Delete(vIndex--)
But anyway your example works. Such approach may by used, if you need to delete some keys, for example odd keys:

Code: Select all

SetBatchLines, -1
vNum := 100000

oArray1 := []
Loop, % vNum
   oArray1.Push("abcdefghij")

oArray2 := oArray1.Clone()

start := A_TickCount

Loop % oArray1.Length()
   if mod(key := vNum--, 2)
      oArray1.Delete(key)

point1 := A_TickCount

Loop % oArray2.Length()
   if mod(A_Index, 2)
      oArray2.Delete(A_Index)

point2 := A_TickCount

MsgBox, % point1 - start "`n" point2 - point1

Return to “Ask for Help (v1)”

Who is online

Users browsing this forum: gongnl, marypoppins_1, mikeyww, Rohwedder, RussF and 130 guests