Thread overview
Sorted output from an associative array
Jan 30, 2013
FG
Jan 30, 2013
bearophile
Jan 30, 2013
bearophile
Jan 30, 2013
FG
Jan 30, 2013
monarch_dodra
Jan 30, 2013
monarch_dodra
January 30, 2013
Let's say i have an array: int[string] wordCount.
How to print key:value pairs ordered by descending value?
Or generally how to to store wordCount in an array of structs or type tuples for later sorting?

In Python I would use something like this:
sorted(wordCount.items(), key=lambda a: a[1], reverse=True).

January 30, 2013
FG:

> Let's say i have an array: int[string] wordCount.

That's an associative array, and it's unsorted just like a Python dict.

In Phobos there is a sorted tree, if you want, that keeps keys sorted.


> How to print key:value pairs ordered by descending value?

There are various solutions. A simple solution is to use a foreach to create an array of 2-tuples (key,value), and then use a schwartzsort to sort just according to values.


> Or generally how to to store wordCount in an array of structs or type tuples for later sorting?

You don't use type tuples for that, just Phobos tuples.
This code is not fast because it appends (untested):


Tuple!(string, int)[] items;
foreach (k, v; wordCount)
    items ~= tuple(k, v);
items.schwartzSort!(it => it[1], "a < b")();


> In Python I would use something like this:
> sorted(wordCount.items(), key=lambda a: a[1], reverse=True).

In Python you use key=itemgetter(1). And in Python2 you use iteritems() for that.

Unfortunately in D there is no byPair() because that ties druntime with std.typecons...

Bye,
bearophile
January 30, 2013
On Wednesday, 30 January 2013 at 15:43:21 UTC, FG wrote:
> Let's say i have an array: int[string] wordCount.
> How to print key:value pairs ordered by descending value?
> Or generally how to to store wordCount in an array of structs or type tuples for later sorting?
>
> In Python I would use something like this:
> sorted(wordCount.items(), key=lambda a: a[1], reverse=True).

Basically, you have to extract and sort a third party data structure.

what you can do is extract only the keys though, and sort them according to a specific pred. Then once your keys are sorted, you can re-obtain the value from the original AA.

Examplea addapted from TDPL:

//----
void main(string[] args)
{
    int[string] freqs = ["a":1, "b":3 , "c":2];

    // Print according to alphabet
    {
        string[] words = freqs.keys;
        sort(words);

        writeln("sorted by alphabet");
        foreach (word; words)
          writefln("%6u\t%s", freqs[word], word);
        writeln();
    }

    // Print according to frequency
    {
        string[] words = freqs.keys;
        sort!((a, b) { return freqs[a] > freqs[b]; })(words);

        writeln("sorted by frequency");
        foreach (word; words)
          writefln("%6u\t%s", freqs[word], word);
        writeln();
    }
}
//----
sorted by alphabet
     1  a
     3  b
     2  c

sorted by frequency
     3  b
     2  c
     1  a
//----
January 30, 2013
> Tuple!(string, int)[] items;
> foreach (k, v; wordCount)
>     items ~= tuple(k, v);
> items.schwartzSort!(it => it[1], "a < b")();

A little tested:

import std.stdio, std.algorithm, std.typecons;

void main() {
    uint[string] wordCount = ["the":200, "val":100, "blue":1000];
    auto items = new Tuple!(string, uint)[wordCount.length];
    uint i = 0;
    foreach (k, v; wordCount)
        items[i++] = tuple(k, v); // avoided append
    items.schwartzSort!(it => it[1], "a < b")();
    writeln(items);
}


Bye,
bearophile
January 30, 2013
On Wednesday, 30 January 2013 at 16:22:37 UTC, monarch_dodra wrote:
> On Wednesday, 30 January 2013 at 15:43:21 UTC, FG wrote:
>> Let's say i have an array: int[string] wordCount.
>> How to print key:value pairs ordered by descending value?
>> Or generally how to to store wordCount in an array of structs or type tuples for later sorting?
>>
>> In Python I would use something like this:
>> sorted(wordCount.items(), key=lambda a: a[1], reverse=True).
>
> Basically, you have to extract and sort a third party data structure.
>
> what you can do is extract only the keys though, and sort them according to a specific pred. Then once your keys are sorted, you can re-obtain the value from the original AA.

Yes, as mentioned, you can use schartzsort for better performance. Even then though, depending on the size of your values, it may be smarter to sort only the keys.
January 30, 2013
Thanks for showing me how to use tuples in this problem.

Just for the record, the sort comparison should be reversed: "a > b".