This is the new home of the egghelp.org community forum.
All data has been migrated (including user logins/passwords) to a new phpBB version.


For more information, see this announcement post. Click the X in the top right-corner of this box to dismiss this message.

[SOLVED] join?

Help for those learning Tcl or writing their own scripts.
Post Reply
r
raider2k
Op
Posts: 140
Joined: Tue Jan 01, 2008 10:42 am

[SOLVED] join?

Post by raider2k »

hi guys ^^

this time im asking about how to make various elements join a list. here it goes:
im reading things from a database which will be handeled with foreach so i can treat each and single element, but thats the "problem" if i can call it like that. things get treated as single elements. example:

i read nicknames from the database and get

john
miles
henry
ashton

and get them as element $nickn in example but want them to be displayed in one single line like here:

john, miles, henry, ashton

i played a bit with join but i wasnt able to find out how to get it into one single line. please help :)
Last edited by raider2k on Tue Apr 14, 2009 8:10 am, edited 1 time in total.
User avatar
arfer
Master
Posts: 436
Joined: Fri Nov 26, 2004 8:45 pm
Location: Manchester, UK

Post by arfer »

It isn't exactly clear where the nicks are coming from. However, the following should help. Your original format of nicks appears to be seperated by newline, as could be the case in a text file.

Code: Select all

# read a text file and create an array from the contents
# each line of the text file consists of a unique nick followed by data associated with that nick
proc readFile {} {

    # the array will be given global scope so that it can be used elsewhere
    global dataArray
    
    # open datafile for reading
    # create a list by splitting the file's contents at each newline character
    # ignore any newline character after the last line
    set id [open db.txt r]
    set dataList [split [read -nonewline $id] \n]
    close $id

    # if dataList created above is not empty, populate dataArray
    # first word of each dataList element is a nick and will become the array name
    # remainder of each dataList element will become the array value
    if {[llength $dataList] != 0} {
        foreach line $dataList {
            set dataArray([lindex $line 0]) [join [lrange $line 1 end]]
        }
    }
    return 0
}

# create a string variable of comma-space delimited nicks from the element names of an array
proc listNicks {} {
    global dataArray

    # if dataArray is not empty, create a nickList from the names of it's elements
    # convert the nickList to a nickString by joining with comma-space delimiter
    # return the nickString to the calling proc
    # zero (0) will be returned to the calling proc if dataArray is empty
    if {[array size dataArray] != 0} {
        set nickList [array names dataArray]
        set nickString [join $nickList ", "]
        return $nickString
    }
    return 0
}
To generalise, if you have a list and want to create a string, the core Tcl 'join' command is used.

join <list> ?joinString?

Without a joinString specified, a space character is used.

It is very important that you understand (in the context of Tcl) the format of what you are starting with and the format of what you wish to end up with. For example, the code pasted above might return :-

arfer, hernick, hisnick, anothernick

It looks like a list and might be referred to in plain English as a list. In Tcl it could not be treated as a list of nicks. It is a comma-space delimited string of nicks. My advise would be to keep the unique nicks in a list so that you always know what you are dealing with programmatically and only convert to a string if and when you want to output :-

Code: Select all

putserv "PRIVMSG #channelname :[join $nickList ", "]
I must have had nothing to do
r
raider2k
Op
Posts: 140
Joined: Tue Jan 01, 2008 10:42 am

Post by raider2k »

hmm ...
i might not have understood what you were trying to explain.
lets explain from my point of view how i tried to make it work:

Code: Select all

set dbquery [::mysql::sel $db "SELECT `nick` FROM `nicktable`;" -list]
if {![string equal $dbquery ""]} {
	foreach name $dbquery {
		set user [lindex $name 0]
		putserv "PRIVMSG $chan :username: $user"
	}
}
if i run this code - as i usually do - the output will be:
username: john
username: miles
username: henry
username: ashton
but i want it to be like this:
usernames: john - miles - henry - ashton
regardless of the character being used to separate single outputs (- in this case)

as i said in my last post, i tried to use the join command as in

Code: Select all

set newnames ""
set newnames2 [join $newnames " "]
as well as

Code: Select all

set newnames ""
set newnames2 [join $newnames]
as i dont know how to handle the join command exactly
User avatar
arfer
Master
Posts: 436
Joined: Fri Nov 26, 2004 8:45 pm
Location: Manchester, UK

Post by arfer »

Code: Select all

set dbquery [::mysql::sel $db "SELECT `nick` FROM `nicktable`;" -list]
if {![string equal $dbquery ""]} {
  foreach name $dbquery {
      lappend users [lindex $name 0]
  }
  putserv "PRIVMSG $chan :usernames: [join $users ", "]
}
I am not familiar with SQL in Tcl but it looks like the query simply returns a list of nicks, in which case the following may be fine :-

Code: Select all

set dbquery [::mysql::sel $db "SELECT `nick` FROM `nicktable`;" -list]
if {![string equal $dbquery ""]} {
  putserv "PRIVMSG $chan :usernames: [join $dbquery ", "]
}
I must have had nothing to do
r
raider2k
Op
Posts: 140
Joined: Tue Jan 01, 2008 10:42 am

Post by raider2k »

mhm ok
and if i want to have - or | or any other separating char i just need to put

Code: Select all

[join $dbquery " - "]
in example, right?

ill try your given example when im at home and hopefully manage to make it work ;)
r
raider2k
Op
Posts: 140
Joined: Tue Jan 01, 2008 10:42 am

Post by raider2k »

arfer wrote:

Code: Select all

set dbquery [::mysql::sel $db "SELECT `nick` FROM `nicktable`;" -list]
if {![string equal $dbquery ""]} {
  foreach name $dbquery {
      lappend users [lindex $name 0]
  }
  putserv "PRIVMSG $chan :usernames: [join $users ", "]
}
outstanding - this one works flawlessly :D
i didnt know about the power of lappend

thank you very much for your appreciated help ^^
User avatar
arfer
Master
Posts: 436
Joined: Fri Nov 26, 2004 8:45 pm
Location: Manchester, UK

Post by arfer »

The join command takes a string argument, rather than a character or sequence of characters as in the split command.

Your example of [join $string " - "] therefore forms a space-hyphen-space delimited string from a list.

Be very careful with any such code because the split command does not work exactly like this in reverse, in case you want to recreate a list.

Consider the following :-

[14:41] <@arfer> % set y [join {one-penny two three}]
[14:41] <@Baal> one-penny two three
[14:41] <@arfer> % set z [split $y " - "]
[14:41] <@Baal> one penny two three

When I recreated the list, I might have expected to get back to {one-penny two three}. That didn't exactly happen for reasons I have explained above.

There are perhaps two distincly different things to consider. How to hold data such that it is easy to manipulate programmatically and, quite seperately, how you want the data to be seen when output.
I must have had nothing to do
r
raider2k
Op
Posts: 140
Joined: Tue Jan 01, 2008 10:42 am

Post by raider2k »

thanks for your "warnings" but i dont think im going to run into such problems (if you can call them as such) at all. IF i like to use join then only because i want single list elements not to be listed as single elements line for line - i want them to be listed in one long line as good and as long as possible ^^
n
nml375
Revered One
Posts: 2860
Joined: Fri Aug 04, 2006 2:09 pm

Post by nml375 »

Since you only select one field from your database table, consider using -flatlist instead of list. Saves you the hazzle of creating a new list...

Code: Select all

set dbquery [::mysql::sel $db "SELECT `nick` FROM `nicktable`;" -flatlist]
if {![string equal $dbquery ""]} {
  putserv "PRIVMSG $chan :usernames: [join $dbquery ", "]
} 
NML_375
Post Reply