# MultiValuedHash

**URL:** <https://www.ruby-forum.com/t/multivaluedhash/112310>\
**Category:** Ruby\
**Created:** [August 17, 2007, 10:56am UTC](https://www.ruby-forum.com/t/multivaluedhash/112310 "2007-08-17T10:56:21Z")\
**Posts on this page:** 4\
**Page:** 1

<div class="post-metadata">

**Author:** ![caefer](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/c/e36b37/32.png) [@caefer](https://www.ruby-forum.com/u/caefer)\
**Post date:** [August 17, 2007, 10:56am UTC](https://www.ruby-forum.com/t/multivaluedhash/112310/1 "2007-08-17T10:56:21Z")

</div>

I have a lot of files in an folder and want loop over the files in a  
special way:

Dir.entries(“f:/test/”).each { |e| filenames.push(e[3…50])}

Now i have an array with the distinct names like:  
a.txt  
b.txt  
c.txt  
d.txt  
…  
z.txt

, but every file “have 20 parts” which i have to proceed:  
00\_a.txt  
01\_a.txt  
02\_a.txt  
…  
19\_a.txt

for i in 0…19  
filenames.map{ |t| if i \< 10 then p “0#{i}_#{t}" else p  
"#{i}_#{t}” end }  
end

I find something about MultiValuedHash, but i didn’t know how i get my  
structure (…the distinct names are the keys and the 20 parts for  
every key as values ) like the raw\_data in an easy way.

raw\_data=[[1,‘a’],[1,‘b’],[1,‘c’],[2,‘a’],[2,[‘b’,‘c’]],  
[3,‘c’]]

class MultiValuedHash \< Hash  
def []=(key,value)  
if has\_key?(key)  
super(key,[value,self[key]].flatten)  
else  
super  
end  
end  
end

hash=MultiValuedHash.new  
raw\_data.each{ |x,y| hash[x]=y }

many thanks & regards  
Christian

---

<div class="post-metadata">

**Author:** ![caefer](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/c/e36b37/32.png) [@caefer](https://www.ruby-forum.com/u/caefer)\
**Post date:** [August 17, 2007, 11:07am UTC](https://www.ruby-forum.com/t/multivaluedhash/112310/2 "2007-08-17T11:07:22Z")

</div>

2007/8/17, Christian [removed\_email\_address@domain.invalid](mailto:removed_email_address@domain.invalid):

> …  
> for i in 0…19  
> [3,‘c’]]
> 
> hash=MultiValuedHash.new  
> raw\_data.each{ |x,y| hash[x]=y }

This is shorter and more efficient:

hash = Hash.new {|h,k| h[k] = []}  
raw\_data.each{ |x,y| hash[x] \<\< y }

And you even do not need a new class. 🙂

Kind regards

robert

---

<div class="post-metadata">

**Author:** ![caefer](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/c/e36b37/32.png) [@caefer](https://www.ruby-forum.com/u/caefer)\
**Post date:** [August 17, 2007, 5:02pm UTC](https://www.ruby-forum.com/t/multivaluedhash/112310/3 "2007-08-17T17:02:03Z")

</div>

> files.rindex(e)}.uniq)

If you use the hash idiom Robert showed you, you won’t have to worry  
about checking for uniqueness, because all keys are unique. They’ll  
be created the first time you use them, and updated each time after  
that. So, the filename is your key, and the file parts get added to  
the array referenced by that key. I also used e[3…-1] instead of  
e[3…50]. This will return the string from the 3rd character to the  
end of the string, regardless of length.

hash = Hash.new {|h,k| h[k] = []}  
Dir.entries(".").each do |e|  
filename = e[3…-1]  
hash[filename].push e  
end

---

<div class="post-metadata">

**Author:** ![caefer](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/c/e36b37/32.png) [@caefer](https://www.ruby-forum.com/u/caefer)\
**Post date:** [August 17, 2007, 4:26pm UTC](https://www.ruby-forum.com/t/multivaluedhash/112310/4 "2007-08-17T16:26:58Z")

</div>

On 17 Aug., 11:05, “Robert K.” [removed\_email\_address@domain.invalid](mailto:removed_email_address@domain.invalid) wrote:

> > a.txt  
> > …
> 
> > ```
> > end
> > 
> > ```
> 
> And you even do not need a new class. 🙂
> 
> Kind regards
> 
> robert

many thanks for the trick

But have anybody an advice how i get the filenames a.txt, b.txt …  
as key and the parts 00\_a.txt , 01\_a.txt, 02\_a.txt as values for  
every key.

i identify a mistake to get the unique names i have to:  
Dir.entries(“f:/base\_data/ADS20/outputdaten/”).each { |e|  
files.push(e[3…50])}  
filenames.push(files.select{|e| files.index(e) !=  
files.rindex(e)}.uniq)

many thanks & regards  
Christian
