Jump to page: 1 2
Thread overview
how to filter associative arrays with foreach ?
Jun 21, 2021
someone
Jun 21, 2021
Ali Çehreli
Jun 24, 2021
someone
Jun 21, 2021
frame
Jun 21, 2021
someone
Jun 21, 2021
wjoe
Jun 21, 2021
someone
Jun 21, 2021
Elronnd
Jun 21, 2021
someone
Jun 21, 2021
someone
June 21, 2021

I often need to iterate through a filtered collection (associative array) as following:

string strComputerIDunwanted = "WS2"; /// associative array key to exclude

foreach (strComputerID, udtComputer; udtComputers) { /// .remove!(a => a == strComputerIDunwanted) ... ?

   if (strComputerID != strComputerIDunwanted) {

      ...

   }

}

Is there a way to filter the collection at the foreach-level to avoid the inner if ?

June 21, 2021
On 6/20/21 8:59 PM, someone wrote:
> I often need to iterate through a filtered collection (associative array) as following:
> 
> ```d
> string strComputerIDunwanted = "WS2"; /// associative array key to exclude
> 
> foreach (strComputerID, udtComputer; udtComputers) { /// ..remove!(a => a == strComputerIDunwanted) ... ?
> 
>     if (strComputerID != strComputerIDunwanted) {
> 
>        ...
> 
>     }
> 
> }
> ```
> 
> Is there a way to filter the collection at the foreach-level to avoid the inner if ?

Two options for byKey and byKeyValue:


import std;

void main() {
  auto aa = [ "WS2" : 42, "WS3" : 43 ];
  string strComputerIDunwanted = "WS2";
  foreach (key; aa.byKey.filter!(k => k != strComputerIDunwanted)) {
    writeln(key, ' ', aa[key]);
  }

  // 't' is the tuple of key and value
  foreach (t; aa.byKeyValue.filter!(t => t.key != strComputerIDunwanted)) {
    writeln(t.key, ' ', t.value);
  }
}

Ali

June 21, 2021

On Monday, 21 June 2021 at 03:59:10 UTC, someone wrote:

>

I often need to iterate through a filtered collection (associative array) as following:

string strComputerIDunwanted = "WS2"; /// associative array key to exclude

foreach (strComputerID, udtComputer; udtComputers) { /// .remove!(a => a == strComputerIDunwanted) ... ?

   if (strComputerID != strComputerIDunwanted) {

      ...

   }

}

Is there a way to filter the collection at the foreach-level to avoid the inner if ?

An associative array is not a range but a struct, so it is extra work to create a range from the AA to apply range functions.

You can get a range from it by using something like std.array.byPair() but for this usage you would be better of with your own function or template.

June 21, 2021

On Monday, 21 June 2021 at 08:35:19 UTC, frame wrote:

>

An associative array is not a range but a struct, so it is extra work to create a range from the AA to apply range functions.

You can get a range from it by using something like std.array.byPair() but for this usage you would be better of with your own function or template.

Crystal-clear. Thanks !

June 21, 2021

On Monday, 21 June 2021 at 03:59:10 UTC, someone wrote:

>

I often need to iterate through a filtered collection (associative array) as following:

string strComputerIDunwanted = "WS2"; /// associative array key to exclude

foreach (strComputerID, udtComputer; udtComputers) { /// .remove!(a => a == strComputerIDunwanted) ... ?

   if (strComputerID != strComputerIDunwanted) {

      ...

   }

}

Is there a way to filter the collection at the foreach-level to avoid the inner if ?

something like this ?

import std.array;
import std.algorithm;

    udtComputers.byPair
        .filter!(p => p.key != strComputerIDunwanted)
        .each!( (p) { /* foreach body */ } );
June 21, 2021
On Monday, 21 June 2021 at 03:59:10 UTC, someone wrote:
> Is there a way to filter the collection at the foreach-level to avoid the inner if ?

Here's how I would do it:

foreach (k, v; coll) {
    if (k == unwanted) continue;
    ...
}

You still have an if, but the actual loop body doesn't have to be nested, so it's easy to follow the control flow.
June 21, 2021

On 6/21/21 5:00 PM, Elronnd wrote:

>

On Monday, 21 June 2021 at 03:59:10 UTC, someone wrote:

>

Is there a way to filter the collection at the foreach-level to avoid the inner if ?

Here's how I would do it:

foreach (k, v; coll) {
    if (k == unwanted) continue;
    ...
}

You still have an if, but the actual loop body doesn't have to be nested, so it's easy to follow the control flow.

Alternatively (if you're ok with this sort of thing):

foreach (k, v; coll) if (k != unwanted) {
}

It's actually visually shorter than doing the filter.

And the benefit to using the if statement over the filter wrapper is that the compiler has to do a lot less work.

-Steve

June 21, 2021
On Monday, 21 June 2021 at 21:00:42 UTC, Elronnd wrote:
> Here's how I would do it:
>
> foreach (k, v; coll) {
>     if (k == unwanted) continue;
>     ...
> }
>
> You still have an if, but the actual loop body doesn't have to be nested, so it's easy to follow the control flow.

almost the same
June 21, 2021

On Monday, 21 June 2021 at 22:08:56 UTC, Steven Schveighoffer wrote:

>

It's actually visually shorter than doing the filter.

Indeed; in a few very-specific situations I usually write code like this since it allows me to concentrate on the task at hand and not on the details to access the needed data, but for the clarity of the example I reformatted my code :)

Same when I code RO properties for classes, I usually do:

private pxxxWhatever1; public whatever() @property { return pxxxWhatever1; }
private pxxxWhatever2; public whatever() @property { return pxxxWhatever2; }
private pxxxWhatever3; public whatever() @property { return pxxxWhatever3; }

It is far easier to read large chunk of similar constructs alongside than one below the other, at least, to me.

June 21, 2021

On Monday, 21 June 2021 at 15:32:09 UTC, wjoe wrote:

>

something like this ?

import std.array;
import std.algorithm;

    udtComputers.byPair
        .filter!(p => p.key != strComputerIDunwanted)
        .each!( (p) { /* foreach body */ } );

This seems really interesting :)

Almost three weeks with D and I still must learn a lot of things, there's a lot to :) !

Thanks for your tip !

« First   ‹ Prev
1 2