Page 1 of 1

Posted: 12 Sep 2017, 15:35
Pid[1] := 1234
Pid[2] := 5678

How to delete array element by value? like this Pid.Remove(5678)

### Re: Easy Quesion about Array

Posted: 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)
}

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

Posted: 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)
}

### Re: Easy Quesion about Array

Posted: 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:""}
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

### Re: Easy Quesion about Array

Posted: 13 Sep 2017, 01:40
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.

### Re: Easy Quesion about Array

Posted: 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.

### Re: Easy Quesion about Array

Posted: 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

### Re: Easy Quesion about Array

Posted: 13 Sep 2017, 11:44
jeeswg wrote:This script records which keys to delete, then deletes them afterwards.
Nifty

### Re: Easy Quesion about Array

Posted: 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)

### Re: Easy Quesion about Array

Posted: 13 Sep 2017, 12:26

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

### Re: Easy Quesion about Array

Posted: 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

### Re: Easy Quesion about Array

Posted: 13 Sep 2017, 12:34
You'll get there eventually. Edit: Forgot the smile:

### Re: Easy Quesion about Array

Posted: 13 Sep 2017, 12:37
I'm not sure. May be, an example?

### Re: Easy Quesion about Array

Posted: 13 Sep 2017, 12:58
Try:

Code: Select all

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

### Re: Easy Quesion about Array

Posted: 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)

### Re: Easy Quesion about Array

Posted: 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.

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.

### Re: Easy Quesion about Array

Posted: 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.

### Re: Easy Quesion about Array

Posted: 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.

### Re: Easy Quesion about Array

Posted: 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.

### Re: Easy Quesion about Array

Posted: 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