NAME

Sidef::Types::Hash::Hash

DESCRIPTION

This class implements a hash (associative array) data type, providing key-value storage and various methods for hash manipulation, iteration, transformation, and set operations.

A Hash is an unordered collection of key-value pairs where each unique key maps to exactly one value. Keys are compared using structural equality.

SYNOPSIS

# Creating hashes
var hash = Hash(a => 1, b => 2, c => 3)
var h = Hash(:foo, :bar)  # Keys with nil values

# Accessing values
say hash{:a}        #=> 1
say hash.item(:b)   #=> 2

# Setting values
hash{:d} = 4
hash.append(e => 5, f => 6)

# Basic operations
say hash.keys       #=> [:a, :b, :c, :d, :e, :f]
say hash.values     #=> [1, 2, 3, 4, 5, 6]
say hash.len        #=> 6
say hash.has(:a)    #=> true

# Iteration
hash.each {|key, value|
    say "#{key} => #{value}"
}

# Transformation
var doubled = hash.map_v { _1 * 2 }
var filtered = hash.grep { |k, v| v > 2 }

# Set operations
var h1 = Hash(a => 1, b => 2)
var h2 = Hash(b => 3, c => 4)

say (h1 | h2)   #=> Hash(a => 1, b => 2, c => 4)  # Union
say (h1 & h2)   #=> Hash(b => 2)                  # Intersection
say (h1 - h2)   #=> Hash(a => 1)                  # Difference
say (h1 ^ h2)   #=> Hash(a => 1, c => 4)          # Symmetric difference

INHERITS

Inherits methods from:

* Sidef::Object::Object

METHODS

&

hash1 & hash2

Returns the intersection of two hashes. The result contains only keys that exist in both hashes, with values taken from the first hash.

var h1 = Hash(a => 1, b => 2, c => 3)
var h2 = Hash(b => 20, c => 30, d => 40)
say (h1 & h2)  #=> Hash(b => 2, c => 3)

Aliases: and, intersection

+

hash1 + hash2

Returns a new hash containing all key-value pairs from both hashes. If a key exists in both, the value from the second hash is used (right-hand precedence).

var h1 = Hash(a => 1, b => 2)
var h2 = Hash(b => 20, c => 30)
say (h1 + h2)  #=> Hash(a => 1, b => 20, c => 30)

Aliases: merge, concat

-

hash1 - hash2

Returns the difference of two hashes. The result contains only keys that exist in the first hash but not in the second.

var h1 = Hash(a => 1, b => 2, c => 3)
var h2 = Hash(b => 20, d => 40)
say (h1 - h2)  #=> Hash(a => 1, c => 3)

Aliases: sub, diff, difference

...

hash...

Returns the hash as a flat list of alternating keys and values.

var h = Hash(a => 1, b => 2)
say h...  #=> [:a, 1, :b, 2]

This is useful for unpacking hashes into argument lists or for converting to other data structures.

Aliases: to_list

==

hash1 == hash2

Returns true if both hashes have the same keys with equal values (structural equality).

var h1 = Hash(a => 1, b => 2)
var h2 = Hash(b => 2, a => 1)
say (h1 == h2)  #=> true

Aliases: eq

^

hash1 ^ hash2

Returns the symmetric difference of two hashes. The result contains keys that exist in either hash but not in both.

var h1 = Hash(a => 1, b => 2)
var h2 = Hash(b => 20, c => 30)
say (h1 ^ h2)  #=> Hash(a => 1, c => 30)

Aliases: xor, symdiff, symmetric_difference

|

hash1 | hash2

Returns the union of two hashes. The result contains all keys from both hashes, with values from the first hash taking precedence for common keys (left-hand precedence).

var h1 = Hash(a => 1, b => 2)
var h2 = Hash(b => 20, c => 30)
say (h1 | h2)  #=> Hash(a => 1, b => 2, c => 30)

Note the difference from + (merge): union keeps left values, merge keeps right values.

Aliases: or, union

hash1 ≠ hash2

Returns true if the two hashes are not equal (different keys or values).

var h1 = Hash(a => 1)
var h2 = Hash(a => 2)
say (h1 ≠ h2)  #=> true

Aliases: !=, ne

append

hash.append(pairs...)

Appends the given key-value pairs to the hash in-place and returns the modified hash. This modifies the original hash.

var h = Hash(a => 1)
h.append(b => 2, c => 3)
say h  #=> Hash(a => 1, b => 2, c => 3)

If a key already exists, its value will be updated.

as_tree

hash.as_tree(root)

Returns the hash as a tree structure represented as nested Pairs, with the given root as the tree's root label.

var h = Hash(a => 1, b => 2)
say h.as_tree(:root)  #=> Pair(:root, [Pair(:a, 1), Pair(:b, 2)])

This is useful for visualizing or processing hashes as hierarchical data structures.

clear

hash.clear

Removes all key-value pairs from the hash and returns the empty hash. This modifies the hash in-place.

var h = Hash(a => 1, b => 2)
h.clear
say h        #=> Hash()
say h.len    #=> 0

collect

hash.collect { |key, value| ... }

Iterates over each key-value pair, calling the block with (key, value), and collects all return values into an Array.

var h = Hash(a => 1, b => 2, c => 3)
var result = h.collect { |k, v|
    "#{k}=#{v}"
}
say result  #=> ["a=1", "b=2", "c=3"]

Aliases: collect_kv

count

hash.count(key)
hash.count { |key, value| ... }

When called with a key, returns 1 if the key exists in the hash, 0 otherwise.

When called with a block, returns the number of key-value pairs for which the block returns true.

var h = Hash(a => 1, b => 2, c => 3, d => 4)

say h.count(:b)             #=> 1
say h.count(:z)             #=> 0
say h.count { |k, v| v > 2 }  #=> 2

count_by

hash.count_by { |key, value| ... }

Returns the count of key-value pairs for which the block returns a true value.

var h = Hash(a => 1, b => 2, c => 3, d => 4)
say h.count_by { |k, v| v.is_even }  #=> 2

delete

hash.delete(keys...)

Removes the specified keys from the hash and returns the deleted values as an Array (or a single value if one key was given). This modifies the hash in-place.

var h = Hash(a => 1, b => 2, c => 3)
say h.delete(:b)        #=> 2
say h.delete(:a, :c)    #=> [1, 3]
say h                   #=> Hash()

Aliases: remove

delete_if

hash.delete_if { |key, value| ... }

Deletes all key-value pairs for which the block returns true. The block receives (key, value) as arguments. Returns the modified hash.

var h = Hash(a => 1, b => 2, c => 3, d => 4)
h.delete_if { |k, v| v.is_even }
say h  #=> Hash(a => 1, c => 3)

This is the destructive version of grep (which returns a new hash).

dig

hash.dig(key, keys...)

Recursively retrieves nested values. Returns the value at the nested key path, or nil if any key in the path doesn't exist.

var h = Hash(
    a => Hash(
        b => Hash(
            c => 42
        )
    )
)

say h.dig(:a, :b, :c)  #=> 42
say h.dig(:a, :x)      #=> nil

This is safer than chaining subscript operations because it won't error if intermediate values are missing.

each

hash.each { |key, value| ... }

Iterates over each key-value pair in the hash, calling the block with (key, value). Returns the hash when a block is given, or acts as an iterator when called without arguments.

var h = Hash(a => 1, b => 2, c => 3)

h.each { |k, v|
    say "#{k} => #{v}"
}

# As iterator
var iter = h.each
loop {
    var (k, v) = iter() \\ break
    say "#{k} => #{v}"
}

Aliases: each_kv, each_pair

each_k

hash.each_k { |key| ... }

Iterates over each key in the hash, calling the block with the key. Returns the hash.

var h = Hash(a => 1, b => 2, c => 3)
h.each_k { |k|
    say k
}

Aliases: each_key

each_v

hash.each_v { |value| ... }

Iterates over each value in the hash, calling the block with the value. Returns the hash.

var h = Hash(a => 1, b => 2, c => 3)
h.each_v { |v|
    say v * 2
}

Aliases: each_value

fetch

hash.fetch(key, default)

Returns the value for the given key if it exists, otherwise returns the default value.

var h = Hash(a => 1, b => 2)

say h.fetch(:a, 0)     #=> 1
say h.fetch(:z, 0)     #=> 0
say h.fetch(:z, nil)   #=> nil

Unlike direct subscript access (hash{key}), fetch allows you to distinguish between a missing key and a key with a nil value.

flip

hash.flip

Returns a new hash with keys and values swapped. The original values become keys and the original keys become values.

var h = Hash(a => 1, b => 2, c => 3)
say h.flip  #=> Hash(1 => :a, 2 => :b, 3 => :c)

Note: If multiple keys have the same value, only one will survive in the flipped hash (last one wins).

Aliases: invert, reverse

get_pair

hash.get_pair(key)

Returns a Pair object containing the given key and its associated value.

var h = Hash(a => 1, b => 2)
var p = h.get_pair(:a)
say p        #=> Pair(:a, 1)
say p.key    #=> :a
say p.value  #=> 1

Returns nil if the key doesn't exist.

get_pairs

hash.get_pairs(keys...)

Returns an Array of Pair objects for the specified keys.

var h = Hash(a => 1, b => 2, c => 3)
var pairs = h.get_pairs(:a, :c)
say pairs  #=> [Pair(:a, 1), Pair(:c, 3)]

Missing keys will produce Pair objects with nil values.

grep

hash.grep { |key, value| ... }

Returns a new hash containing only the key-value pairs for which the block returns true. The block receives (key, value) as arguments.

var h = Hash(a => 1, b => 2, c => 3, d => 4)
var evens = h.grep { |k, v| v.is_even }
say evens  #=> Hash(b => 2, d => 4)

This is the non-destructive version of delete_if.

Aliases: grep_kv, select

grep_v

hash.grep_v { |value| ... }

Returns a new hash containing only the key-value pairs for which the block (called with value only) returns true.

var h = Hash(a => 1, b => 2, c => 3, d => 4)
var evens = h.grep_v { .is_even }
say evens  #=> Hash(b => 2, d => 4)

Aliases: grep_val

has

hash.has(key)

Returns true if the given key exists in the hash, false otherwise.

var h = Hash(a => 1, b => nil)

say h.has(:a)  #=> true
say h.has(:b)  #=> true  (key exists even with nil value)
say h.has(:z)  #=> false

Aliases: exists, has_key, haskey, contain, include, contains, includes

is_empty

hash.is_empty

Returns true if the hash contains no key-value pairs, false otherwise.

var h1 = Hash()
var h2 = Hash(a => 1)

say h1.is_empty  #=> true
say h2.is_empty  #=> false

item

hash.item(key)

Returns the value associated with the given key, or nil if the key doesn't exist.

var h = Hash(a => 1, b => 2)

say h.item(:a)  #=> 1
say h.item(:z)  #=> nil

This is equivalent to subscript notation: hash{key}.

items

hash.items(keys...)

Returns an Array of values for the specified keys. Returns nil for keys that don't exist.

var h = Hash(a => 1, b => 2, c => 3)
say h.items(:a, :c, :z)  #=> [1, 3, nil]

keys

hash.keys

Returns an Array containing all keys in the hash.

var h = Hash(a => 1, b => 2, c => 3)
say h.keys  #=> [:a, :b, :c]

Note: Hash keys are unordered, so the order of keys in the returned array is not guaranteed.

kv

hash.kv

Returns an Array of Pair objects, where each Pair contains a key and its associated value.

var h = Hash(a => 1, b => 2)
say h.kv  #=> [Pair(:a, 1), Pair(:b, 2)]

# Useful for iteration with destructuring
h.kv.each { |pair|
    say "#{pair.key} => #{pair.value}"
}

Aliases: to_a, pairs, to_array

len

hash.len

Returns the number of key-value pairs in the hash.

var h = Hash(a => 1, b => 2, c => 3)
say h.len  #=> 3

Aliases: size, length

lsel

hash.lsel(keys_array)

Performs linear selection: returns a new hash with the specified keys. Keys that don't exist in the original hash will have nil values in the result.

var h = Hash(a => 1, b => 2)
var selected = h.lsel([:a, :c])
say selected  #=> Hash(a => 1, c => nil)

This differs from slice, which omits missing keys.

Aliases: linsel, linear_selection

map

hash.map { |key, value| ... }

Transforms the hash by calling the block with (key, value) for each pair. The block should return a new key-value pair (as a two-element array or pair). Returns a new hash.

var h = Hash(a => 1, b => 2)
var mapped = h.map { |k, v|
    (k.uc, v * 10)
}
say mapped  #=> Hash(A => 10, B => 20)

Aliases: map_kv

map_v

hash.map_v { |key, value| ... }

Returns a new hash with the same keys but with values transformed by the block. The block receives (key, value) and should return the new value.

var h = Hash(a => 1, b => 2, c => 3)
var doubled = h.map_v { |k, v| v * 2 }
say doubled  #=> Hash(a => 2, b => 4, c => 6)

# Block can also take just the value
var squared = h.map_v { _1 ** 2 }
say squared  #=> Hash(a => 1, b => 4, c => 9)

Aliases: map_val

max_by

hash.max_by { |key, value| ... }

Returns the key-value Pair for which the block returns the maximum value. The block receives (key, value).

var h = Hash(a => 3, b => 1, c => 5, d => 2)
var max_pair = h.max_by { |k, v| v }
say max_pair  #=> Pair(:c, 5)

merge_values

hash.merge_values(other_hash)

Updates values in the hash for keys that also exist in the other hash. Only existing keys are affected (no new keys are added). Modifies and returns the hash.

var h1 = Hash(a => 1, b => 2, c => 3)
var h2 = Hash(b => 20, c => 30, d => 40)

h1.merge_values(h2)
say h1  #=> Hash(a => 1, b => 20, c => 30)

Note: Key :d was not added because it didn't exist in h1.

min_by

hash.min_by { |key, value| ... }

Returns the key-value Pair for which the block returns the minimum value. The block receives (key, value).

var h = Hash(a => 3, b => 1, c => 5, d => 2)
var min_pair = h.min_by { |k, v| v }
say min_pair  #=> Pair(:b, 1)

new

Hash.new
Hash.new(pairs...)

Creates and returns a new Hash object, optionally initialized with the given key-value pairs.

var h1 = Hash.new
var h2 = Hash.new(a => 1, b => 2)
var h3 = Hash(a => 1, b => 2)  # Shorthand

Aliases: call

same_keys

hash.same_keys(other)

Returns true if the hash has exactly the same keys as the given object (another hash, array, or other iterable), false otherwise. Values are not compared.

var h1 = Hash(a => 1, b => 2)
var h2 = Hash(a => 10, b => 20)
var h3 = Hash(a => 1, c => 3)

say h1.same_keys(h2)  #=> true
say h1.same_keys(h3)  #=> false

set_keys

hash.set_keys(keys...)

Sets the specified keys with nil values and returns the hash. Modifies the hash in-place.

var h = Hash(a => 1)
h.set_keys(:b, :c)
say h  #=> Hash(a => 1, b => nil, c => nil)

This is useful for initializing hash keys before setting their actual values.

slice

hash.slice(keys...)

Returns a new hash containing only the specified keys and their values from the original hash. Keys that don't exist in the original are omitted.

var h = Hash(a => 1, b => 2, c => 3, d => 4)
var subset = h.slice(:a, :c, :z)
say subset  #=> Hash(a => 1, c => 3)

Note: Key :z was omitted because it doesn't exist in the original hash.

sort

hash.sort
hash.sort { |a, b| ... }

Returns an Array of Pairs sorted by keys. If a block is provided, uses it as a comparison function for sorting keys.

var h = Hash(c => 3, a => 1, b => 2)
say h.sort  #=> [Pair(:a, 1), Pair(:b, 2), Pair(:c, 3)]

# Custom sort
var rev = h.sort { |a, b| b <=> a }
say rev  #=> [Pair(:c, 3), Pair(:b, 2), Pair(:a, 1)]

sort_by

hash.sort_by { |key, value| ... }

Returns an Array of Pairs sorted by the values returned by the block. The block receives (key, value).

var h = Hash(a => 3, b => 1, c => 2)
var sorted = h.sort_by { |k, v| v }
say sorted  #=> [Pair(:b, 1), Pair(:c, 2), Pair(:a, 3)]

# Sort by key length
var by_len = h.sort_by { |k, v| k.len }

to_bag

hash.to_bag

Converts the hash's keys to a Bag object.

var h = Hash(a => 1, b => 2, c => 3)
var bag = h.to_bag
say bag  #=> Bag(:a, :b, :c)

The hash values are ignored; only keys are used to create the Bag.

to_s

hash.to_s

Returns a string representation of the hash.

var h = Hash(a => 1, b => 2)
say h.to_s  #=> "Hash(a => 1, b => 2)"

Aliases: dump, to_str

to_set

hash.to_set

Converts the hash's keys to a Set object.

var h = Hash(a => 1, b => 2, c => 3)
var set = h.to_set
say set  #=> Set(:a, :b, :c)

The hash values are ignored; only keys are used to create the Set.

values

hash.values

Returns an Array containing all values in the hash.

var h = Hash(a => 1, b => 2, c => 3)
say h.values  #=> [1, 2, 3]

Note: Since hash keys are unordered, the order of values in the returned array is not guaranteed to match any particular order.

EXAMPLES

Frequency Counting

var text = "hello world"
var freq = Hash()

text.each_char { |char|
    freq{char} := 0
    freq{char}++
}

say freq  #=> Hash(h => 1, e => 1, l => 3, ...)

Grouping Data

var people = [
    Hash(name => "Alice", age => 30),
    Hash(name => "Bob", age => 25),
    Hash(name => "Carol", age => 30)
]

var by_age = Hash()
people.each { |person|
    var age = person{:age}
    by_age{age} := []
    by_age{age} << person
}

Transforming Data

var prices = Hash(apple => 1.50, banana => 0.75, orange => 2.00)

# Apply discount
var discounted = prices.map_v { _1 * 0.9 }

# Filter expensive items
var expensive = prices.grep { |k, v| v > 1.00 }

Merging with Custom Logic

var defaults = Hash(color => :red, size => :medium, count => 1)
var options = Hash(size => :large)

# Keep defaults for missing keys
var config = defaults + options
say config  #=> Hash(color => :red, size => :large, count => 1)

SEE ALSO

Sidef::Types::Array::Array, Sidef::Types::Set::Set, Sidef::Types::Bag::Bag

AUTHOR

Daniel "Trizen" Șuteu

LICENSE

This module is free software; you can redistribute it and/or modify it under the same terms as Sidef itself.