Easy Quesion about Array Topic is solved
Easy Quesion about Array
Pid[1] := 1234
Pid[2] := 5678
How to delete array element by value? like this Pid.Remove(5678)
Pid[2] := 5678
How to delete array element by value? like this Pid.Remove(5678)
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: 4549
- Joined: 29 Mar 2015, 09:41
- Contact:
Re: Easy Quesion about Array Topic is solved
NoHelgef wrote:Maybe like this
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
For something like this I might use an associative array instead of a linear array, like so:
For the linear array approach:
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
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
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
- 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
WARNING: copy your posts/messages before hitting Submit as you may lose them due to CAPTCHA
Re: Easy Quesion about Array
Your code in function.jeeswg wrote:Linear array approach
Code: Select all
removeVal(arr,val){
Loop % vLen := arr.Length()
if (arr[vLen--] = val)
arr.RemoveAt(vLen+1)
}
1 and 2. There was no specification.jeeswg wrote:Note:
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: 4549
- Joined: 29 Mar 2015, 09:41
- Contact:
Re: Easy Quesion about Array
No, both namely delete keys, yours remove. That may be undesirable, if I expect to see other keys in their old places.jeeswg wrote:both teadrinker's and Helgef's functions clear rather than delete keys (which may be desirable)
Your approach is good, but nobody said that an array should be linear.
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:
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
WARNING: copy your posts/messages before hitting Submit as you may lose them due to CAPTCHA
Re: Easy Quesion about Array
Niftyjeeswg wrote:This script records which keys to delete, then deletes them afterwards.
-
- Posts: 4549
- Joined: 29 Mar 2015, 09:41
- Contact:
Re: Easy Quesion about Array
jeeswg, this code
you may fearlessly replace with this:
Code: Select all
oRemove := []
for vKey, vValue in oArray
if (vValue = 2)
oRemove.Push(vKey)
Loop, % vIndex := oRemove.Length()
oArray.Delete(oRemove[vIndex--])
Code: Select all
for vKey, vValue in oArray
if (vValue = 2)
oArray.Delete(vKey)
Re: Easy Quesion about Array
Noteadrinker wrote:jeeswg, this codeyou may fearlessly replace with this:Code: Select all
oRemove := [] for vKey, vValue in oArray if (vValue = 2) oRemove.Push(vKey) Loop, % vIndex := oRemove.Length() oArray.Delete(oRemove[vIndex--])
Code: Select all
for vKey, vValue in oArray if (vValue = 2) oArray.Delete(vKey)
-
- Posts: 4549
- 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
Re: Easy Quesion about Array
You'll get there eventually. Edit: Forgot the smile:
-
- Posts: 4549
- Joined: 29 Mar 2015, 09:41
- Contact:
Re: Easy Quesion about Array
I'm not sure. May be, an example?
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
WARNING: copy your posts/messages before hitting Submit as you may lose them due to CAPTCHA
-
- Posts: 4549
- 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)
Re: Easy Quesion about Array
teadrinker wrote:for me it's unexpected behavior.
It is not something unique for ahk. Easy to miss though, I sure have at times and probably will again.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.
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.teadrinker wrote: Then this way:Code: Select all
for vKey, vValue in oArray.Clone() if (vValue = 2) oArray.Delete(vKey)
-
- Posts: 4549
- Joined: 29 Mar 2015, 09:41
- Contact:
Re: Easy Quesion about Array
Thanks, I'll try to keep it on mind. Cheers.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.
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:
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.
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
homepage | tutorials | wish list | fun threads | donate
WARNING: copy your posts/messages before hitting Submit as you may lose them due to CAPTCHA
WARNING: copy your posts/messages before hitting Submit as you may lose them due to CAPTCHA
Re: Easy Quesion about Array
The array might contain huge strings. You will copy them and then discard them after the loop. It could be very wasteful.I can't remember what exactly the possible reasons against cloning were
-
- Posts: 4549
- Joined: 29 Mar 2015, 09:41
- Contact:
Re: Easy Quesion about Array
@jeeswg
is incorrect, you needed
But anyway your example works. Such approach may by used, if you need to delete some keys, for example odd keys:
It's really an interesting observation. Notice, that the codedeleting the last key has almost no cost, and deleting the first key has a big cost.
Code: Select all
oArray.Delete(oArray[vIndex--])
Code: Select all
oArray.Delete(vIndex--)
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