Thread overview
Filter and sort associative array
Jan 11
Alex
January 11
I am just learning D. So far, I am impressed by its elegance and power.

I have an associative array bool[string]. I want to filter it by value (!bool), then extract the keys and sort them. I am struggling with the syntax and working with ranges. I can't find any documentation related to filtering associative arrays.

This is what I currently have, but it doesn't compile:

auto sortedStrings = myAssocArray.byKeyValue.filter!((string k,value) => !value).assocArray.keys.sort();


January 11
On Fri, Jan 11, 2019 at 03:20:20PM +0000, Head Scratcher via Digitalmars-d-learn wrote:
> I am just learning D. So far, I am impressed by its elegance and power.
> 
> I have an associative array bool[string]. I want to filter it by value (!bool), then extract the keys and sort them. I am struggling with the syntax and working with ranges. I can't find any documentation related to filtering associative arrays.
> 
> This is what I currently have, but it doesn't compile:
> 
> auto sortedStrings = myAssocArray.byKeyValue.filter!((string k,value) =>
> !value).assocArray.keys.sort();

I recommend using std.array.byPair rather than .byKeyValue, like this:

auto sortedStrings = myAssocArray.byPair
	.filter!(pair => !pair[1])	// pair[1] is the value
	.map!(pair => pair[0])		// pair[0] is the key
	.array
	.sort;

The .array call is needed because .byPair returns a non-random access range, which cannot be sorted. So you need to create an array first then sort that.

Also, there's no need to reconstruct another AA with the filtered entries -- it allocates a new AA which is wasteful.  All you really need is the filter the keys, then sort the keys.


T

-- 
If the comments and the code disagree, it's likely that *both* are wrong. -- Christopher
January 11
On 1/11/19 10:20 AM, Head Scratcher wrote:
> I am just learning D. So far, I am impressed by its elegance and power.
> 
> I have an associative array bool[string]. I want to filter it by value (!bool), then extract the keys and sort them. I am struggling with the syntax and working with ranges. I can't find any documentation related to filtering associative arrays.
> 
> This is what I currently have, but it doesn't compile:
> 
> auto sortedStrings = myAssocArray.byKeyValue.filter!((string k,value) => !value).assocArray.keys.sort();
> 
>

import std.range;
import std.algorithm;
import std.array;

auto sortedStrings = myAssocArray
    .byKeyValue
    .filter!(kvp => !kvp.value) // kvp = key value pair
    .map!(kvp => kvp.key)       // map to the key strings
    .array                      // form a sortable array
    .sort;                      // sort it

Note the nice formatting to show how the range pipeline goes, and allows for comments explaining each step.

-Steve
January 11
Thank you. This works great. What I don't understand is how a key-value pair ends up being a set of strings. Where did the value of the key-value pair get removed?  According to the library documentation, the array function "allocates an array and initializes it with copies of the elements of range r." So wouldn't the resulting array contain pairs? And if so, how does the sort work on pairs?
January 11
On Friday, 11 January 2019 at 16:02:27 UTC, Head Scratcher wrote:
> Thank you. This works great. What I don't understand is how a key-value pair ends up being a set of strings. Where did the value of the key-value pair get removed?  According to the library documentation, the array function "allocates an array and initializes it with copies of the elements of range r." So wouldn't the resulting array contain pairs? And if so, how does the sort work on pairs?

By map you map the pair to its key resp. its first element. The result of the map contains the right-hand side of the "=>" expression only.
January 11
On Friday, 11 January 2019 at 16:06:48 UTC, Alex wrote:
> On Friday, 11 January 2019 at 16:02:27 UTC, Head Scratcher wrote:
>> Thank you. This works great. What I don't understand is how a key-value pair ends up being a set of strings. Where did the value of the key-value pair get removed?  According to the library documentation, the array function "allocates an array and initializes it with copies of the elements of range r." So wouldn't the resulting array contain pairs? And if so, how does the sort work on pairs?
>
> By map you map the pair to its key resp. its first element. The result of the map contains the right-hand side of the "=>" expression only.

Ah, that makes sense. Thank you for the explanation.