From: basi
Subject: Newbie Question: How do I mass-populate a hash table?
Date: 
Message-ID: <1104601776.735936.18200@c13g2000cwb.googlegroups.com>
Hello,
How do I mass-populate a hash table? A statement for each index-value
pair like the ones below can be daunting if you have a couple hundred
items.

(setf (gethash 'one *hash-table*) "one")
(setf (gethash 'two *hash-table*) "two")
...

Is there something similar in intent to the list command "(list 'a 'b
c')", something like:

(setf (gethash 'one "one" 'two "two" 'three "three" ... *hash-table*)

Ideally, I'd like to read the index-value pairs from a file or database
table, and for each pair insert the pair through a function like

(defun hash-table-populator (index value hash-table)
(append index value hash-table)))
but that would be sometime in the future for me. 

Thanks,
Basi

From: Wade Humeniuk
Subject: Re: Newbie Question: How do I mass-populate a hash table?
Date: 
Message-ID: <lQBBd.40690$KO5.36332@clgrps13>
basi wrote:
> Hello,
> How do I mass-populate a hash table? A statement for each index-value
> pair like the ones below can be daunting if you have a couple hundred
> items.
> 
> (setf (gethash 'one *hash-table*) "one")
> (setf (gethash 'two *hash-table*) "two")
> ...
> 
> Is there something similar in intent to the list command "(list 'a 'b
> c')", something like:
> 
> (setf (gethash 'one "one" 'two "two" 'three "three" ... *hash-table*)
> 
> Ideally, I'd like to read the index-value pairs from a file or database
> table, and for each pair insert the pair through a function like
> 

Populating a hash table using a property list.  A property list
has a form like '(one "ONE" two "TWO" ....).

(defun populate-hash-table (table property-list)
   (loop for (key value) on property-list by #'cddr
         do (setf (gethash key table) value)))

CL-USER 15 > (defparameter *hash-table* (make-hash-table))
*HASH-TABLE*

CL-USER 16 > (populate-hash-table *hash-table*
                      (loop for i from 1 to 100
                            for string = (format nil ···@(~R~)" i)
                            collect (intern string)
                            collect string))
NIL

CL-USER 17 > (gethash 'ten *hash-table*)
"TEN"
T

CL-USER 18 > (describe *hash-table*)
; Loading fasl file C:\Program Files\Xanalys\LispWorks\lib\4-3-0-0\modules\util\describe.fsl
;  Loading fasl file C:\Program 
Files\Xanalys\LispWorks\lib\4-3-0-0\modules\streams\indentin.fsl
;  Loading fasl file C:\Program Files\Xanalys\LispWorks\lib\4-3-0-0\modules\util\inspvals.fsl
;  Loading fasl file C:\Program 
Files\Xanalys\LispWorks\lib\4-3-0-0\modules\concat\fli-insp.fsl
; Loading fasl file C:\Program 
Files\Xanalys\LispWorks\lib\4-3-0-0\patches\describe\0001\0001.fsl
; Loaded public patch DESCRIBE 1.1


#<EQL Hash Table{100} 21464ADC> is a HASH-TABLE
TWENTY-FIVE       "TWENTY-FIVE"
THREE             "THREE"
FIFTY-SIX         "FIFTY-SIX"
EIGHTY-SEVEN      "EIGHTY-SEVEN"
TWENTY-FOUR       "TWENTY-FOUR"
TWO               "TWO"
FIFTY-FIVE        "FIFTY-FIVE"
EIGHTY-SIX        "EIGHTY-SIX"
ONE               "ONE"
ONE HUNDRED       "ONE HUNDRED"
TWENTY-THREE      "TWENTY-THREE"
FIFTY-FOUR        "FIFTY-FOUR"
EIGHTY-FIVE       "EIGHTY-FIVE"
NINETY-NINE       "NINETY-NINE"
TWENTY-TWO        "TWENTY-TWO"
FIFTY-THREE       "FIFTY-THREE"
EIGHTY-FOUR       "EIGHTY-FOUR"
TWENTY-ONE        "TWENTY-ONE"
NINETY-EIGHT      "NINETY-EIGHT"
FIFTY-TWO         "FIFTY-TWO" ........


CL-USER 19 >

Wade
From: Pascal Costanza
Subject: Re: Newbie Question: How do I mass-populate a hash table?
Date: 
Message-ID: <cr6pbp$o7e$1@newsreader2.netcologne.de>
basi wrote:
> Hello,
> How do I mass-populate a hash table? A statement for each index-value
> pair like the ones below can be daunting if you have a couple hundred
> items.
> 
> (setf (gethash 'one *hash-table*) "one")
> (setf (gethash 'two *hash-table*) "two")
> ...
> 
> Is there something similar in intent to the list command "(list 'a 'b
> c')", something like:
> 
> (setf (gethash 'one "one" 'two "two" 'three "three" ... *hash-table*)
> 
> Ideally, I'd like to read the index-value pairs from a file or database
> table, and for each pair insert the pair through a function like
> 
> (defun hash-table-populator (index value hash-table)
> (append index value hash-table)))
> but that would be sometime in the future for me. 

I don't think there's something available that does these things for 
you. Since you have explicitly marked this as a newbie question: Have 
you tried to implement this for yourself? Shouldn't be too hard and you 
would learn something along the way...


Pascal


-- 
The big bang way only works for god, everybody else has to use 
evolution. - David Moon
From: Frank Buss
Subject: Re: Newbie Question: How do I mass-populate a hash table?
Date: 
Message-ID: <cr6tjp$29s$1@newsreader2.netcologne.de>
"basi" <··········@yahoo.com> wrote:

> How do I mass-populate a hash table? A statement for each index-value
> pair like the ones below can be daunting if you have a couple hundred
> items.
> 
> (setf (gethash 'one *hash-table*) "one")
> (setf (gethash 'two *hash-table*) "two")

I like the way how you can do it in Perl, because it is self-documenting, 
when reading it. In Lisp you can write a function:

(defun fill-hash (hashtable values)
  (dolist (value values)
    (destructuring-bind (key equal-greater value) value
      (unless (eql equal-greater '=>) (error "syntax error"))
      (setf (gethash key hashtable) value))))

(defun test ()
  (let ((hashtable (make-hash-table)))
    (fill-hash hashtable '((key1 => value1)
                           (key2 => value2)
                           (key3 => value3)))
    hashtable))

CL-USER > (describe (test))

#<EQL Hash Table{3} 2068CB04> is a HASH-TABLE
KEY1      VALUE1
KEY3      VALUE3
KEY2      VALUE2

-- 
Frank Bu�, ··@frank-buss.de
http://www.frank-buss.de, http://www.it4-systems.de
From: Pascal Bourguignon
Subject: Re: Newbie Question: How do I mass-populate a hash table?
Date: 
Message-ID: <87sm5l9e72.fsf@thalassa.informatimago.com>
"basi" <··········@yahoo.com> writes:

> Hello,
> How do I mass-populate a hash table? A statement for each index-value
> pair like the ones below can be daunting if you have a couple hundred
> items.

The questions are: Where do you have them? 
and:               How often? 

When I have them in a file and once, I usually just use emacs and a
couple of replace-regexp passes to end with:

> (setf (gethash 'one *hash-table*) "one")
> (setf (gethash 'two *hash-table*) "two")

which I can then easily (load "table.lisp")


Otherwise, it's easy enough to write a (with-open-file (...) (loop
... (read) ... (setf (gethash key table) value) ...)) loop.


> Is there something similar in intent to the list command "(list 'a 'b
> c')", something like:
> 
> (setf (gethash 'one "one" 'two "two" 'three "three" ... *hash-table*)

Ow! You want to write such a statement with a couple hundred couples
of items, and take the risk to miss one and shift the following keys
and values... Nice.  But if you really find it worthwhile, it's not
hard to write a multiple-gethash defsetf function.  Note however than
you cannot pass more CALL-ARGUMENTS-LIMIT arguments to a function and
that this limit can be as low as 50, so you won't be able to setf more
than 24 keys portably.  It seems that this does not apply to macros,
so instead you could write a fill-hash macro:

    (fill-hash *hash-table*
         'one   "one" 
         'two   "two"
         'three "three" 
         ;; ...
         'two-hundred "two-hundred" )


But serriously:

> Ideally, I'd like to read the index-value pairs from a file or database
> table, and for each pair insert the pair through a function like
> 
> (defun hash-table-populator (index value hash-table)
> (append index value hash-table)))
> but that would be sometime in the future for me. 

Why?  What's so hard in reading a file?  If you format correctly the
file, and are assured of the correct formating, it would reduce just
to one (READ), plus the populating loop:

Assume that such a hash table:

(let ((h (make-hash-table))) 
    (setf (gethash 1 h) "un")
    (setf (gethash 2 h) "deux") 
    (setf (gethash 3 h) "trois") 
    h)

would be stored as a single sexp:

((3 . "trois") 
 (2 . "deux") 
 (1 . "un"))

Then you only have to write this:

   (with-open-file (hash "hash.sexp")
     (loop with h = (make-hash-table)
           for couple in (read hash nil nil) ; read is called once.
           while couple
           do (setf (gethash (car couple) h) (cdr couple))
           finally (return h)))


On the other hand, if you prefer to store each couple in its own sexp
in the file:

(3 . "trois") 
(2 . "deux") 
(1 . "un")

Then you only have to write this:

   (with-open-file (hash "hash.sexp")
     (loop with h = (make-hash-table)
           for couple = (read hash nil nil) ; read is called several times.
           while couple
           do (setf (gethash (car couple) h) (cdr couple))
           finally (return h)))


Of course, you could avoid dots in the input:

(3  "trois") 
(2  "deux") 
(1  "un")

Then you only have to write this:

   (with-open-file (hash "hash.sexp")
     (loop with h = (make-hash-table)
           for couple = (read hash nil nil) ; read is called several times.
           while couple
           do (setf (gethash (first couple) h) (second couple))
           finally (return h)))



-- 
__Pascal_Bourguignon__               _  Software patents are endangering
()  ASCII ribbon against html email (o_ the computer industry all around
/\  1962:DO20I=1.100                //\ the world http://lpf.ai.mit.edu/
    2001:my($f)=`fortune`;          V_/   http://petition.eurolinux.org/
From: David Sletten
Subject: Re: Newbie Question: How do I mass-populate a hash table?
Date: 
Message-ID: <IKGBd.55818$gd.48974@twister.socal.rr.com>
basi wrote:

> Hello,
> How do I mass-populate a hash table? A statement for each index-value
> pair like the ones below can be daunting if you have a couple hundred
> items.
> 
> (setf (gethash 'one *hash-table*) "one")
> (setf (gethash 'two *hash-table*) "two")
> ...
> 
> Is there something similar in intent to the list command "(list 'a 'b
> c')", something like:
> 
> (setf (gethash 'one "one" 'two "two" 'three "three" ... *hash-table*)
> 
> Ideally, I'd like to read the index-value pairs from a file or database
> table, and for each pair insert the pair through a function like
> 
> (defun hash-table-populator (index value hash-table)
> (append index value hash-table)))
> but that would be sometime in the future for me. 
> 
> Thanks,
> Basi
> 
In a way, you've kind of answered your own question. The point is that 
normally you won't initialize a hash-table from a literal. You will 
create it by reading information from somewhere external. The main 
strength of a hash-table over other implementations of a dictionary 
(such as an association list) is the speed of lookup. But this is only 
an issue once your dictionary reaches a certain size. If you look at the 
toy examples in Perl textbooks, you see that Perl's syntax does make it 
convenient to create a literal hash with 5 key/value pairs. But in Lisp 
why bother? Just use an a-list or a property list.

David Sletten

(By the way, you do realize that APPEND has nothing to do with 
hash-tables, right?)
From: Tayssir John Gabbour
Subject: Re: Newbie Question: How do I mass-populate a hash table?
Date: 
Message-ID: <1104654512.578146.53760@c13g2000cwb.googlegroups.com>
There are implementation-specific ways to do this. So some agree with
you. For example, in CLisp:

(make-hash-table :initial-contents '((1 . 2) (8 . 9)))

This initializes the hashtable with an association list.

(If you're not familiar with those dots, it's just that (foo . bar)
represents a single cons cell where the car is foo and the cdr is bar.
If it were (foo bar), the car would still be foo; but the cdr would be
(bar) or in equivalent notation (bar . nil).)


MfG,
Tayssir
From: basi
Subject: Re: Newbie Question: How do I mass-populate a hash table?
Date: 
Message-ID: <1104702444.583502.206880@c13g2000cwb.googlegroups.com>
Hello,

Thank you all for the replies. I'm going for the suggestion to use the
property list data structure. Where I am now in this trip to learn
Lisp, I find property list to be a smaller step to make than hash
table. I will revisit hash tables, of course, as it is more efficient.
So far the trip is surprisingly pleasant; but I have only made a few
baby steps, and they don't even look like authentic Lisp steps.

Basi


basi wrote:
> Hello,
> How do I mass-populate a hash table? A statement for each index-value
> pair like the ones below can be daunting if you have a couple hundred
> items.
>
> (setf (gethash 'one *hash-table*) "one")
> (setf (gethash 'two *hash-table*) "two")
> ...
>
> Is there something similar in intent to the list command "(list 'a 'b
> c')", something like:
>
> (setf (gethash 'one "one" 'two "two" 'three "three" ... *hash-table*)
>
> Ideally, I'd like to read the index-value pairs from a file or
database
> table, and for each pair insert the pair through a function like
>
> (defun hash-table-populator (index value hash-table)
> (append index value hash-table)))
> but that would be sometime in the future for me.
> 
> Thanks,
> Basi
From: Alex Mizrahi
Subject: Re: Newbie Question: How do I mass-populate a hash table?
Date: 
Message-ID: <33r4jnF414ijoU1@individual.net>
(message (Hello 'basi)
(you :wrote  :on '(1 Jan 2005 09:49:36 -0800))
(

 b> How do I mass-populate a hash table? A statement for each index-value
 b> pair like the ones below can be daunting if you have a couple hundred
 b> items.

 b> (setf (gethash 'one *hash-table*) "one")
 b> (setf (gethash 'two *hash-table*) "two")
 b> ...

for example,

CL-USER>
 (let ((ht (make-hash-table)))
   (map nil (lambda (x y) (setf (gethash x ht) y))
  '(one two three)
  '(1 2 3))
    ht)

#S(HASH-TABLE EQL (THREE . 3) (TWO . 2) (ONE . 1))


)
(With-best-regards '(Alex Mizrahi) :aka 'killer_storm)
(prin1 "People, who lust for the Feel of keys on their fingertips (c)
Inity"))