## Easy Quesion about Array Topic is solved

Get help with using AutoHotkey and its commands and hotkeys
masheen
Posts: 295
Joined: 06 Dec 2016, 14:10

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

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

### Re: Easy Quesion about Array

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)
}
``````
Posts: 2096
Joined: 29 Mar 2015, 09:41
Contact:

### Re: Easy Quesion about Array  Topic is solved

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)
}``````
jeeswg
Posts: 6902
Joined: 19 Dec 2016, 01:58
Location: UK

### Re: Easy Quesion about Array

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

Code: Select all

``````q::
oPID := {1114:"",2224:""}
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: 4479
Joined: 17 Jul 2016, 01:02
Contact:

### Re: Easy Quesion about Array

jeeswg wrote:Linear array approach

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.
Posts: 2096
Joined: 29 Mar 2015, 09:41
Contact:

### Re: Easy Quesion about Array

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.
jeeswg
Posts: 6902
Joined: 19 Dec 2016, 01:58
Location: UK

### Re: Easy Quesion about Array

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: 4479
Joined: 17 Jul 2016, 01:02
Contact:

### Re: Easy Quesion about Array

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

### Re: Easy Quesion about Array

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: 4479
Joined: 17 Jul 2016, 01:02
Contact:

### Re: Easy Quesion about Array

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
Posts: 2096
Joined: 29 Mar 2015, 09:41
Contact:

### Re: Easy Quesion about Array

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: 4479
Joined: 17 Jul 2016, 01:02
Contact:

### Re: Easy Quesion about Array

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

### Re: Easy Quesion about Array

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

### Re: Easy Quesion about Array

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
Posts: 2096
Joined: 29 Mar 2015, 09:41
Contact:

### Re: Easy Quesion about Array

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: 4479
Joined: 17 Jul 2016, 01:02
Contact:

### Re: Easy Quesion about Array

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.

Code: Select all

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

### Re: Easy Quesion about Array

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.
jeeswg
Posts: 6902
Joined: 19 Dec 2016, 01:58
Location: UK

### Re: Easy Quesion about Array

@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: 4479
Joined: 17 Jul 2016, 01:02
Contact:

### Re: Easy Quesion about Array

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.
Posts: 2096
Joined: 29 Mar 2015, 09:41
Contact:

### Re: Easy Quesion about Array

@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``````