Search code examples
hashrakurakudo

Is there a Raku method that allows a hash value to be sorted and split from its pair?


I am currently trying to use hashes in an array to find the keys and values of each specific item in the array. I am able to do this and both the keys and the values are separate when I haven't sorted the array, but when I create a sorted array such as:

my @sorted_pairs = %counts{$word}.sort(*.value);

It binds the values together. Is there a method for sorted hash values that allow the pairs to be split into separate entities within the array? I want to be able to access the "word" string and the count or number of times that word was seen as an integer, separately.

I am using this source as a reference. I have tried a handful of these methods and while it does seem to sort the array by numeric value given the output:

sorted array : [do => 1 rest => 1 look => 1 wanted => 1 give => 1 imagine => 2 read => 2 granted => 2 ever => 2 love => 2 gonna => 2 feel => 2 meant => 2 like => 2 you => 2 live => 3 wrote => 3 come => 3 know => 3 are => 3 mom => 4]

it doesn't separate the key and value from one another.


Solution

  • Word-counting in Raku

    You might want to save your results as a (Bag-ged) array-of-hashes (pairs?), then print out either .keys or .values as necessary.

    raku -e 'my @aoh = words.Bag.pairs.sort(*.values).reverse; \
            .say for @aoh;'  Ishmael.txt
    

    Sample Input (Ishmael.txt):

    Call me Ishmael.  Some years ago--never mind how long precisely --having little or no money in my purse, and nothing particular to interest me on shore, I thought I would sail about a little and see the watery part of the world.  It is a way I have of driving off the spleen, and regulating the circulation.  Whenever I find myself growing grim about the mouth; whenever it is a damp, drizzly November in my soul; whenever I find myself involuntarily pausing before coffin warehouses, and bringing up the rear of every funeral I meet; and especially whenever my hypos get such an upper hand of me, that it requires a strong moral principle to prevent me from deliberately stepping into the street, and methodically knocking people's hats off--then, I account it high time to get to sea as soon as I can.
    

    Using the code above you get the following Output (full output truncated by specifying $_.value >= 4):

    raku -e 'my @aoh = words.Bag.pairs.sort(*.values).reverse; \
            .say if ($_.value >= 4) for @aoh ;'  Ishmael.txt
    I => 8
    the => 7
    and => 6
    of => 4
    to => 4
    a => 4
    

    And it's simple enough to return just .keys by changing the second statement to .keys.put for @aoh:

    $ raku -e 'my @aoh = words.Bag.pairs.sort(*.values).reverse; \
              .keys.put if ($_.value >= 4) for @aoh ;'  Ishmael.txt
    
    I
    the
    and
    a
    to
    of
    

    Or return just .values by changing the second statement to .values.put for @aoh:

    $ raku -e 'my @aoh = words.Bag.pairs.sort(*.values).reverse; \
              .values.put if ($_.value >= 4) for @aoh ;'  Ishmael.txt
    
    8
    7
    6
    4
    4
    4
    

    [Note: the above is a pretty quick-and-dirty example of word-counting code in Raku. It doesn't handle punctuation, capitalization, etc., but it's a start.]

    https://docs.raku.org/language/hashmap#Looping_over_hash_keys_and_values