1

Update Solved the compiling error, now the only problem with the code is how to sort the dict alphabetically for pretty printing.

I am refactoring an argument parser from python into Genie, however I found myself stuck in how to sort the items form a dict before appending them to a list.

In python it is as simple as:

    lines.append("Options:")
    if len(self.options):
        for name, option in sorted(self.options.items()):
            lines.append("  %s: %s" % (name, option.values))
    else:
        lines.append("  [none]")

self.options is declared as self.options = {}

Now how can print the contents of the dict, but sorted?

Here is the code where I am stuck:

def ListOptions()
    var lines = new list of string

    lines.add("Options:")
    if _options.size != 0
        for name in _options.keys
            lines.add("  %s: %s" % (name, _options.values))
    else
        lines.add("  [none]")

ListOptions is a method within a class, and I declared _options as _options:new dict of string, string

There is no compiling error in that section of the code anymore. My question is how to sort the elements of the dict before adding them to the list lines?

lf_araujo
  • 1,991
  • 2
  • 16
  • 39
  • When you say "argument parser" do you mean arguments passed from the command line to the program? – AlThomas Aug 27 '16 at 10:17
  • I mean as in [here](https://github.com/dmulholland/clio)... But I guess what I am trying to achieve has nothing to do with this problem I am facing... The problems are how to iterate over a dict that has been sorted alphabetically... – lf_araujo Aug 27 '16 at 11:48
  • 1
    If you are looking to parse command line arguments you should be looking at GLib's OptionContext and OptionEntry. This is good for most purposes. For an example in Vala see http://stackoverflow.com/questions/33431446/how-to-do-optioncontext-parsing-on-an-instance – AlThomas Sep 04 '16 at 14:09

2 Answers2

2

A dict of is in reality a Gee.HashMap of K, V, so you can look up what type the keys property is.

keys is of type Gee.Set of G which doesn't have a sort method.

It does however derive from Gee.Collection of G which we can use to make a new temporary list of string (which is Gee.ArrayList under the hood and does have a sort method).

I have put this into a sort_string_collection function (which could even be Generic, since it's not specific to strings, but I didn't bother because it's not easily possible with Genie at the moment).

With added test code, to make it a MCVE, the result looks like this:

[indent=4]

def sorted_string_collection (collection: Gee.Collection of string): Gee.Iterable of string
    var l = new list of string
    l.add_all (collection);
    l.sort ()
    return l;

def list_options (_options: dict of string, string): list of string
    var lines = new list of string

    lines.add("Options:")
    if _options.size != 0
        for name in sorted_string_collection (_options.keys)
            lines.add(@"  $name: $(_options[name])")
    else
        lines.add("  [none]")

    return lines

init
    var opts = new dict of string, string
    opts["z"] = "23"
    opts["abc"] = "42"
    opts["pi"] = "3.141"
    var l = list_options (opts)
    for var s in l
        print (s)

Or even more minimalistic (if we ever get to use stackoverflow Documentation for Genie, this would be a good example):

[indent=4]

def sorted_string_collection (collection: Gee.Collection of string): Gee.Iterable of string
    var l = new list of string
    l.add_all (collection);
    l.sort ()
    return l;

init
    var dic = new dict of string, string
    dic["z"] = "23"
    dic["abc"] = "42"
    dic["pi"] = "3.141"
    for k in sorted_string_collection (dic.keys)
        print (@"$k: $(dic[k])")
Jens Mühlenhoff
  • 14,565
  • 6
  • 56
  • 113
  • 1
    If you want efficient searching from key to value and sorting of keys and values then Gee's TreeMap is better. TreeMap implements Gee.SortedMap so you get both `ascending_keys` and `ascending_entries` properties. – AlThomas Sep 04 '16 at 14:21
  • That's true, it's always wise to choose the most suited data structure. You should think of converting your comment to an answer as it's an alternative to mine. – Jens Mühlenhoff Sep 05 '16 at 09:47
  • Thanks you two! What is the function of @ in print(@ ... ) and lines_add(@ ...)? – lf_araujo Sep 09 '16 at 22:28
  • @lf_araujo That is called an **interpolated string literal**, everything in the string that has a `$` (dollar) prefix will be replaced with the result of evaluating the expression. For simple vars `$varname` is sufficient, for complex expression parenthesis are required `$(my_expression)`. – Jens Mühlenhoff Sep 11 '16 at 14:55
  • Or rather the concept is called string interpolation, the Vala tutorial calls them "string templates" and the Genie page calls them "text templates". Anyway you should get the idea ;). – Jens Mühlenhoff Sep 11 '16 at 14:57
  • I have created a new question for this: https://stackoverflow.com/questions/39437587/how-does-string-interpolation-string-templates-work – Jens Mühlenhoff Sep 11 '16 at 15:18
2

Based on Thomas and Jens comments, one can also use TreeMap. Here is how it would look:

[indent=4]

uses
    Gee

init
    var dic = new TreeMap of string, string
    dic["z"] = "23"
    dic["abc"] = "42"
    dic["pi"] = "3.141"
    for k in dic.ascending_keys
        print (@"$k: $(dic[k])")
lf_araujo
  • 1,991
  • 2
  • 16
  • 39