### Re: Sort Associative Array by Key

On Tuesday, 27 August 2019 at 20:35:16 UTC, bachmeier wrote:

On Tuesday, 27 August 2019 at 20:14:21 UTC, Machine Code wrote:

It isn't really hard:

It really is hard. foo.byPair.array.sort!((a, b) => a.key <
b.key).map!(a => a.value); is a lot to digest for someone
learning the language. There's a big difference between not
being hard for someone that understands what each piece does
and not being hard for someone new to D. At a minimum, it would
help to write it

foo.byPair
.array
.sort!((a, b) => a.key < b.key)
.map!(a => a.value);

I wrote expression with string lambdas for one purpose:
when u see very simple beauty thing that is working and u totally
doesn't understand how exactly, ur curiosity should do the rest
of the work. it's worth sorting out.

if man wanted just do his job, he got this too.

### Re: Sort Associative Array by Key

On Tuesday, 27 August 2019 at 16:25:00 UTC, Samir wrote:
As I've mentioned on the list before, I really struggle to
understand how some of the std.algorithm functions such as
`map` work when combined with things like `array`, `sort` and
especially `zip` but really appreciate the support I find here
on the forum.

A few months ago I stuggled with that too. Meanwhile I think I
got it.

Let's examine just the first step in this sequence:

writeln(foo.byPair);

[Tuple!(string, "key", int, "value")("BZP", 5), Tuple!(string,
"key", int, "value")("VXE", 8), Tuple!(string, "key", int,
"value")("JLC", 2)]

Well, this look like an array of tuples, each tuple containing a
key and a value. I assume, that you understand tuples, I think,
they are not the problem here. The problem arises, because the
result of "foo.byPair" isn't an array. Actually writeln converts
the result to an array, before printing it (or at least it
pretends to do so). You can see this with:

writeln(typeof(foo.byPair).stringof);

Which is:

MapResult!(__lambda2, Result)

Ooops, what's that? Having a look at the documentation isn't very
instructive (at least at beginners level):

auto byPair(AA)(AA aa)
if (isAssociativeArray!AA);

That's almost all you get. Almost, because the description
mentions, that the return value is a forward range. Ah, it's a
range. I'm not sure, how much you know about ranges. If you want
to understand that stuff, you should study them. E.g. try to
write some ranges of your own.

When thinking of a range, I imagine it as sort of a voucher for
something like an array. You can use that voucher to get elements
from that array. In case of an forward range, you are restricted
to get the elements ony by one from the beginning. You get them
by using the function front(), which all ranges provide. Let's
try it:

auto something = foo.byPair;
writeln(something.front);

And we get:

Tuple!(string, "key", int, "value")("BZP", 5)

That's indeed the first of our elements. We don't know yet, what
this range is doing behind the sceens. But I can tell you: When
calling byPair it hasn't done much: It just signed that voucher
and handed it out to you (that's called lazy evaluation, contrary
to eager evaluation). Maybe you never use that voucher. In that
case it would be wasted time to calculate all the elements, that
are never used.

The moment you call front, that range starts to do some of the
work. It assembles the first item of the range and hand's this
out to you. Then it stops again - the other items are not yet
calculated. That's done, when you call front again (but before
you need to call popFront, to remove the first item, else you
would get the item, you allready have, once again). And so on.

Now we know, how to use this range and that's what "array" does:
It calls front and popFront as long as there are more elements
(this can be checked by calling empty on the range), and puts
them into an array. But what we don't understand yet is that
strange type of the range: MapResult!(__lambda2, Result).

For that, we should have a look at the implementation (I'm using
http://dpldocs.info/experimental-docs/std.array.byPair.html for
that, because it has a link to the documentation at the bottom),
we find out, that byPair is implemented using byKeyValue and map:

return aa.byKeyValue
.map!(pair => tuple!("key", "value")(pair.key,
pair.value));

byKeyValue is defined in object, which has no source code - I
guess it's implemented directly in the compiler somehow. By using
typeof, we find out that the type is "Result" and by using
writeln we find out, that the result of byKeyValue looks like an
array of Pairs of pointers. Again it's a range, that we can use
like above.

This range (think again of a voucher) is now send to map. Map
needs, beside this range, a function. You could write that
function like:

auto make_tuple(Pair pair)
{
return tuple!("key", "value")(pair.key, pair.value);
}

Than the above could be written as

return aa.byKeyValue.map!(make_tuple);

Beside the fact, that I cannot find the definition of Pair (and
therefore would need to make a template instead of the function),
it's not necessary to write that function explicitly. There is a
way, to write functions more compressed, namely by using =>, like
it's done above. Those functions are called lambda-functions
(because at some places a greek lambda symbol was used for the
function parameter).

Now, map is lazy too. It just remembers that function, the
"voucher" it got and hand's you an other voucher. That's all.
This new voucher is called "MapResult", which is actually a
struct with functions "front", "popFront" and "empty" (and some
more, but we don't care). And this struct has two
template-parameters, namely a function and a range. We know that
range already, it's Result from byKeyValue. And that function,
which has no name, got the name "__lambda2" from

### Re: Sort Associative Array by Key

On Tuesday, 27 August 2019 at 20:14:21 UTC, Machine Code wrote:

It isn't really hard:

It really is hard. foo.byPair.array.sort!((a, b) => a.key <
b.key).map!(a => a.value); is a lot to digest for someone
learning the language. There's a big difference between not being
hard for someone that understands what each piece does and not
being hard for someone new to D. At a minimum, it would help to
write it

foo.byPair
.array
.sort!((a, b) => a.key < b.key)
.map!(a => a.value);

### Re: Sort Associative Array by Key

On Tuesday, 27 August 2019 at 16:25:00 UTC, Samir wrote:

On Sunday, 25 August 2019 at 17:01:23 UTC, a11e99z wrote:

auto foo = ["VXE":8, "BZP":5, "JLC":2];
foo.byPair.array.sort!"a[0]

On Sunday, 25 August 2019 at 19:03:10 UTC, JN wrote:

I think normal lambdas are better than these string ones:

foo.byPair.array.sort!((a, b) => a[0] < b[0]).map!(a =>
a[1]).writeln;

On Sunday, 25 August 2019 at 21:13:05 UTC, Paul Backus wrote:

You can also use names instead of numeric indices:

foo.byPair.array.sort!((a, b) => a.key < b.key).map!(a =>
a.value);

a11e99z, JN, Paul:  Thank you all for your replies and help.
As I've mentioned on the list before, I really struggle to
understand how some of the std.algorithm functions such as
`map` work when combined with things like `array`, `sort` and
especially `zip` but really appreciate the support I find here
on the forum.

Samir

It isn't really hard:
.array() turns the range into an array, so that sort() can work.
sort() takes "callback" function to test the elements while
sorting and determine the proper position in the array.
map() select the property from each element, putting that
requested property into an array.

### Re: Sort Associative Array by Key

On Sunday, 25 August 2019 at 17:01:23 UTC, a11e99z wrote:

auto foo = ["VXE":8, "BZP":5, "JLC":2];
foo.byPair.array.sort!"a[0]

On Sunday, 25 August 2019 at 19:03:10 UTC, JN wrote:

I think normal lambdas are better than these string ones:

foo.byPair.array.sort!((a, b) => a[0] < b[0]).map!(a =>
a[1]).writeln;

On Sunday, 25 August 2019 at 21:13:05 UTC, Paul Backus wrote:

You can also use names instead of numeric indices:

foo.byPair.array.sort!((a, b) => a.key < b.key).map!(a =>
a.value);

a11e99z, JN, Paul:  Thank you all for your replies and help.  As
I've mentioned on the list before, I really struggle to
understand how some of the std.algorithm functions such as `map`
work when combined with things like `array`, `sort` and
especially `zip` but really appreciate the support I find here on
the forum.

Samir

### Re: Sort Associative Array by Key

On Sunday, 25 August 2019 at 19:03:10 UTC, JN wrote:

I think normal lambdas are better than these string ones:

foo.byPair.array.sort!((a, b) => a[0] < b[0]).map!(a =>
a[1]).writeln;

You can also use names instead of numeric indices:

foo.byPair.array.sort!((a, b) => a.key < b.key).map!(a =>
a.value);

### Re: Sort Associative Array by Key

On Sunday, 25 August 2019 at 17:01:23 UTC, a11e99z wrote:

On Sunday, 25 August 2019 at 16:54:33 UTC, Samir wrote:
Is there a way to output the values of an associative array
based on the lexicographic order of the keys?

For example, if foo = ["VXE":8, "BZP":5, "JLC":2], I'd like to
output something like:

5
2
8

auto foo = ["VXE":8, "BZP":5, "JLC":2];
foo.byPair.array.sort!"a[0]

I think normal lambdas are better than these string ones:

foo.byPair.array.sort!((a, b) => a[0] < b[0]).map!(a =>
a[1]).writeln;

### Re: Sort Associative Array by Key

On Sunday, 25 August 2019 at 16:54:33 UTC, Samir wrote:
Is there a way to output the values of an associative array
based on the lexicographic order of the keys?

For example, if foo = ["VXE":8, "BZP":5, "JLC":2], I'd like to
output something like:

5
2
8

auto foo = ["VXE":8, "BZP":5, "JLC":2];
foo.byPair.array.sort!"a[0]

### Sort Associative Array by Key

Is there a way to output the values of an associative array based
on the lexicographic order of the keys?

For example, if foo = ["VXE":8, "BZP":5, "JLC":2], I'd like to
output something like:

5
2
8

Thanks!
Samir

### sort associative array by key

What is the best way to have a function sort an associative array
by key?  The following yields a conversion error.

double[string] aa_sort(double[string] aa) {
return aa.keys.sort;
}

### Re: sort associative array by key

On 11/23/12, dsmith d...@nomail.com wrote:
What is the best way to have a function sort an associative array
by key?  The following yields a conversion error.

double[string] aa_sort(double[string] aa) {
return aa.keys.sort;
}

Hashes are unordered, you can't sort them by key because they don't
preserve any order during insertion/removal. You can alternatively
return a sorted array:

string[] keys_sorted(double[string] aa) {
string[] keys = aa.keys;
sort(keys);  // from std.algorithm;
return keys;
}

### Re: sort associative array by key

On 11/23/2012 07:09 PM, dsmith wrote:

What is the best way to have a function sort an associative array by
key?  The following yields a conversion error.

double[string] aa_sort(double[string] aa) {
return aa.keys.sort;
}

A hash table is unsorted by definition. What is it that you want to do
exactly?

The following will generate a newly allocated dynamic array of key-value
pairs, sorted by key:

import std.algorithm, std.typecons;

Tuple!(string, double)[] aa_sort(double[string] aa){
typeof(return) r=[];
foreach(k,v;aa) r~=tuple(k,v);
sort!q{a[0]b[0]}(r);
return r;
}

### Re: sort associative array by key

On Friday, 23 November 2012 at 18:24:07 UTC, Timon Gehr wrote:

On 11/23/2012 07:09 PM, dsmith wrote:
What is the best way to have a function sort an associative
array by

key?  The following yields a conversion error.

double[string] aa_sort(double[string] aa) {
return aa.keys.sort;
}

A hash table is unsorted by definition. What is it that you
want to do exactly?

The following will generate a newly allocated dynamic array of
key-value pairs, sorted by key:

import std.algorithm, std.typecons;

Tuple!(string, double)[] aa_sort(double[string] aa){
typeof(return) r=[];
foreach(k,v;aa) r~=tuple(k,v);
sort!q{a[0]b[0]}(r);
return r;
}

Suppose the string is of the format 201207, 21208, ...
So aa[201207] == 123.45

How do you parse the tuple for the key and the value?

### Re: sort associative array by key

On 11/23/2012 07:48 PM, dsmith wrote:

On Friday, 23 November 2012 at 18:24:07 UTC, Timon Gehr wrote:

On 11/23/2012 07:09 PM, dsmith wrote:

What is the best way to have a function sort an associative array by
key?  The following yields a conversion error.

double[string] aa_sort(double[string] aa) {
return aa.keys.sort;
}

A hash table is unsorted by definition. What is it that you want to do
exactly?

The following will generate a newly allocated dynamic array of
key-value pairs, sorted by key:

import std.algorithm, std.typecons;

Tuple!(string, double)[] aa_sort(double[string] aa){
typeof(return) r=[];
foreach(k,v;aa) r~=tuple(k,v);
sort!q{a[0]b[0]}(r);
return r;
}

Suppose the string is of the format 201207, 21208, ...
So aa[201207] == 123.45

How do you parse the tuple for the key and the value?

tpl[0] is the key and tpl[1] is the value in this case.