Official Join method or function

Get help with using AutoHotkey (v1.1 and older) and its commands and hotkeys
danielo515
Posts: 58
Joined: 18 Feb 2015, 15:06

Official Join method or function

15 Apr 2015, 09:53

Hello,

I was wondering if there is any official join method for arrays or at least a join function that accepts arrays.
The only thing I found on the documentation is the following function in the part of

Code: Select all

Join(sep, params*) {
    for index,param in params
        str .= param . sep
    return SubStr(str, 1, -StrLen(sep))
}
Which can be used like this:

Code: Select all

MsgBox % Join("`n", "one", "two", "three") 
substrings := ["one", "two", "three"]
MsgBox % Join("-", substrings*)
That is not beautiful but works. Is there any better approach?
Coco
Posts: 771
Joined: 29 Sep 2013, 20:37
Contact:

Re: Official Join method or function

15 Apr 2015, 10:41

Unfortunately, there is no built-in Join() function. I would love for StrSplit() to have a counterpart.
danielo515 wrote:That is not beautiful but works.
I don't think one could write it any better. There might be slight variations but one would still need to loop through the array..
geek
Posts: 1052
Joined: 02 Oct 2013, 22:13
Location: GeekDude
Contact:

Re: Official Join method or function

15 Apr 2015, 10:47

I prefer to put the separator first, so I can omit the second parameter of the SubStr

Code: Select all

Join(sep, params*) {
    for index,param in params
        str .= sep . param
    return SubStr(str, StrLen(sep)+1)
}
danielo515
Posts: 58
Joined: 18 Feb 2015, 15:06

Re: Official Join method or function

15 Apr 2015, 15:09

Coco wrote:Unfortunately, there is no built-in Join() function. I would love for StrSplit() to have a counterpart.
danielo515 wrote:That is not beautiful but works.
I don't think one could write it any better. There might be slight variations but one would still need to loop through the array..
I don't say that you don't need to loop the array, but for example, the way you have to call the function with the asterisk it's not very standard. Also having to specify the separator first makes impossible to leave this to a default value if non specified.

For me a better approach would be

Array.join() or Array.join(',')

Regards
danielo515
Posts: 58
Joined: 18 Feb 2015, 15:06

Re: Official Join method or function

15 Apr 2015, 15:09

GeekDude wrote:I prefer to put the separator first, so I can omit the second parameter of the SubStr

Code: Select all

Join(sep, params*) {
    for index,param in params
        str .= sep . param
    return SubStr(str, StrLen(sep)+1)
}
Thank you GeekDude, that approach is even better and simpler.
I'll go for it.
geek
Posts: 1052
Joined: 02 Oct 2013, 22:13
Location: GeekDude
Contact:

Re: Official Join method or function

15 Apr 2015, 15:23

A fun thing I like to do sometimes is override the string base. That way, I can do fun things like this

Code: Select all

MsgBox, % ",".Join("a", "b", "fish")


class _{
static _:="".base.base:=_
Join(p*){
for k,v in p
s.=this v
return SubStr(s,StrLen(this)+1)
}}
Edit: Alternatively

Code: Select all

MsgBox, % ", ".join("a", "b", "fish")

Join(s,p*){
static _:="".base.Join:=Func("Join")
for k,v in p
o.=s v
return SubStr(o,StrLen(s)+1)
}
danielo515
Posts: 58
Joined: 18 Feb 2015, 15:06

Re: Official Join method or function

15 Apr 2015, 15:45

Wow, that is quite complex. I did not know anything about POO in AHK, so any explanation wold be welcome.

Anyway your proposal is exactly the opposite of what I wanted :P
And it works with regular strings, not arrays, but good to know at the end.
geek
Posts: 1052
Joined: 02 Oct 2013, 22:13
Location: GeekDude
Contact:

Re: Official Join method or function

15 Apr 2015, 17:29

danielo515 wrote:Wow, that is quite complex. I did not know anything about POO in AHK, so any explanation wold be welcome.
POO? :lol: not sure what you mean there. Some reading online leads me to believe that's the french abbreviation for OOP, but I'm still not sure
danielo515 wrote:Anyway your proposal is exactly the opposite of what I wanted :P
And it works with regular strings, not arrays, but good to know at the end.
Python does it as "".join(), so why shouldn't I implement it that way?
danielo515
Posts: 58
Joined: 18 Feb 2015, 15:06

Re: Official Join method or function

16 Apr 2015, 01:01

GeekDude wrote: POO? :lol: not sure what you mean there. Some reading online leads me to believe that's the french abbreviation for OOP, but I'm still not sure
Sorry. I don't know about French, but in spanish it is. My bad :D
GeekDude wrote:
Python does it as "".join(), so why shouldn't I implement it that way?
Just because I'm not familiar with it :lol: , no just joking. The reason is because I want to join Arrays, and you are adding the join method to the string object, and you are passing the elements to join as arguments, not as an array.
hd0202
Posts: 183
Joined: 04 Oct 2013, 03:07
Location: Germany near Cologne

Re: Official Join method or function

16 Apr 2015, 01:15

Do you mean this:

Code: Select all

MsgBox, % ", ".join(["a", "b", "fish"])
MsgBox, % ", ".join("a", "c", "fish")
array := ["a", "d", "fish"]
MsgBox, % ", ".join(array)

Join(s,p*){
  static _:="".base.Join:=Func("Join")
  for k,v in p
  {
    if isobject(v)
      for k2, v2 in v
        o.=s v2
    else
      o.=s v
  }
  return SubStr(o,StrLen(s)+1)
}
Hubert
danielo515
Posts: 58
Joined: 18 Feb 2015, 15:06

Re: Official Join method or function

16 Apr 2015, 02:00

hd0202 wrote:Do you mean this:

Code: Select all

MsgBox, % ", ".join(["a", "b", "fish"])
MsgBox, % ", ".join("a", "c", "fish")
array := ["a", "d", "fish"]
MsgBox, % ", ".join(array)

Join(s,p*){
  static _:="".base.Join:=Func("Join")
  for k,v in p
  {
    if isobject(v)
      for k2, v2 in v
        o.=s v2
    else
      o.=s v
  }
  return SubStr(o,StrLen(s)+1)
}
Hubert
Exactly that! Sorry I did not know that this would work without the asterisk in the function call. On the documentation it is stated that you have to add the asterisk if you have declared the function with the asterisk. It is called Variadic Functions. Could you please explain me the difference?

Thanks in advance.
hd0202
Posts: 183
Joined: 04 Oct 2013, 03:07
Location: Germany near Cologne

Re: Official Join method or function

16 Apr 2015, 03:11

here is a new version with 6 methods,
which each use "Join", the method GeekDude provided - and with my extension
and "Join2", the original method from the docu:

Code: Select all

out .= "1a --> " ", ".join(["a", "b", "fish"]) "`n"
out .= "1b --> " ", ".join2(["a", "b", "fish"]) "`n"
out .= "2a --> " ", ".join("a", "c", "fish") "`n"
out .= "2b --> " ", ".join2("a", "c", "fish") "`n"

array := ["a", "e", "fish"]
out .= "3a --> " ", ".join(array) "`n"
out .= "3b --> " ", ".join2(array) "`n"
out .= "4a --> " ", ".join(array*) "`n"
out .= "4b --> " ", ".join2(array*) "`n"
out .= "5a --> " join(",", array) "`n"
out .= "5b --> " join2(",", array) "`n"
out .= "6a --> " join(",", array*) "`n"
out .= "6b --> " join2(",", array*) "`n"

msgbox, % out

Join(s,p*){
  static _:="".base.Join:=Func("Join")
  for k,v in p
  {
    if isobject(v)
      for k2, v2 in v
        o.=s v2
    else
      o.=s v
  }
  return SubStr(o,StrLen(s)+1)
}
Join2(s,p*){
  for k,v in p
      o.=s v
  return SubStr(o,StrLen(s)+1)
}
It shows that all function calls (1a ... 6a) are possible with "Join" and that only one function call (6b) is possible with "Join2" and needs "array*"

Hubert
geek
Posts: 1052
Joined: 02 Oct 2013, 22:13
Location: GeekDude
Contact:

Re: Official Join method or function

16 Apr 2015, 10:49

danielo515 wrote:The reason is because I want to join Arrays, and you are adding the join method to the string object, and you are passing the elements to join as arguments, not as an array.
There is not much difference between arguments and arrays. As is shown elsewhere in this thread, you can add a * to convert between them.
If you want to pass an array as arguments, just do this ", ".join(["a", "b", "c"]*).
I must note now that python's join function actually does take an array and not arguments, so I should probably make my function do the same.

Ok, now for OOP in AHK. Before I start explaining, are you familiar with OOP in other languages?
User avatar
nnnik
Posts: 4500
Joined: 30 Sep 2013, 01:01
Location: Germany

Re: Official Join method or function

21 Dec 2016, 10:58

GeekDude wrote:
danielo515 wrote:The reason is because I want to join Arrays, and you are adding the join method to the string object, and you are passing the elements to join as arguments, not as an array.
There is not much difference between arguments and arrays. As is shown elsewhere in this thread, you can add a * to convert between them.
If you want to pass an array as arguments, just do this ", ".join(["a", "b", "c"]*).
I must note now that python's join function actually does take an array and not arguments, so I should probably make my function do the same.

Ok, now for OOP in AHK. Before I start explaining, are you familiar with OOP in other languages?
No you should do so because AutoHotkeys StrSplit Function returns an array.
Recommends AHK Studio
geek
Posts: 1052
Joined: 02 Oct 2013, 22:13
Location: GeekDude
Contact:

Re: Official Join method or function

21 Dec 2016, 11:50

StrSplit works fine in both cases. I see no technical reason to pick one of these over the other, though I do prefer the second one because I can easily make the separator an optional parameter if I wanted to. I would suspect the second also performs a few microseconds faster, but I haven't run any tests.

Code: Select all

MsgBox, % Join(",", StrSplit("a|b|c", "|")*)

Join(Sep, Params*)
{
	for k, v in Params
		out .= Sep . v
	return SubStr(Out, 1+StrLen(Sep))
}

Code: Select all

MsgBox, % Join(StrSplit("a|b|c", "|"), ",")

Join(Array, Sep)
{
	for k, v in Array
		out .= Sep . v
	return SubStr(Out, 1+StrLen(Sep))
}
Garbidge_1
Posts: 14
Joined: 02 Sep 2014, 23:03

Re: Official Join method or function

21 Dec 2016, 22:25

Code: Select all

MsgBox, % Join(",", StrSplit("a|b|c", "|")*)  ; string in, string out

array := Join("`n", StrSplit("a|b|c", "|"), "bar")  ; array in[1], array out

s=
for k, v in array
	s .= v

MsgBox % s

Join(Sep:="", Params*) {
	; returns array if at least first param is an array:
	if IsObject(Params[1]) { 
		Out:={}
		for k, v in Params
			if isObject(v) {
				for i, j in v
					out.Push(j), Sep!="" ? out.Push(Sep) :""
			} else
				out.Push(v), Sep!="" ? out.Push(Sep) :""
		if( Sep !="" && out[out.MaxIndex()] = Sep )
			out.RemoveAt(out.MaxIndex())
		return Out		
	}	
	VarSetCapacity(Out, 10000)  ; speed boost?
	for k, v in Params
		out .= Sep . v
	return SubStr(Out, 1+StrLen(Sep))
}
tmplinshi
Posts: 1604
Joined: 01 Oct 2013, 14:57

Re: Official Join method or function

22 Dec 2016, 00:14

You can overwrite the default Array.

Code: Select all

arr := ["a", "b", "c"]
MsgBox, % arr.join()
MsgBox, % arr.join("`n")
return

Array(items*) {
	items.base := ArrayEx
	return items
}

class ArrayEx
{
	join(sep := ",") {
		for k, v in this {
			out .= sep v
		}
		return SubStr(out, StrLen(sep)+1)
	}
}
geek
Posts: 1052
Joined: 02 Oct 2013, 22:13
Location: GeekDude
Contact:

Re: Official Join method or function

22 Dec 2016, 08:28

That doesn't affect the arrays returned by built in functions such as StrSplit though.
buzard
Posts: 6
Joined: 25 May 2021, 04:40

Re: Official Join method or function

25 May 2021, 04:48

Hello,

I know this post is actually quite old. but please considere the join function in this manner, that do nopt need extra removal of extra separator :

Code: Select all

Join(s, h, t*)
{
	for _,x in t
		h .= s . x
	return h
}

Return to “Ask for Help (v1)”

Who is online

Users browsing this forum: Rohwedder and 115 guests