www.digitalmars.com         C & C++   DMDScript  

digitalmars.D.learn - how to filter associative arrays with foreach ?

reply someone <someone somewhere.com> writes:
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 ?
Jun 20 2021
next sibling parent reply =?UTF-8?Q?Ali_=c3=87ehreli?= <acehreli yahoo.com> writes:
On 6/20/21 8:59 PM, someone wrote:
 I often need to iterate through a filtered collection (associative=20
 array) as following:
=20
 ```d
 string strComputerIDunwanted =3D "WS2"; /// associative array key to ex=
clude
=20
 foreach (strComputerID, udtComputer; udtComputers) { /// ..remove!(a =3D=
=20
 a =3D=3D strComputerIDunwanted) ... ?
=20
  =C2=A0=C2=A0 if (strComputerID !=3D strComputerIDunwanted) {
=20
  =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 ...
=20
  =C2=A0=C2=A0 }
=20
 }
 ```
=20
 Is there a way to filter the collection at the foreach-level to avoid=20
 the inner if ?
Two options for byKey and byKeyValue: import std; void main() { auto aa =3D [ "WS2" : 42, "WS3" : 43 ]; string strComputerIDunwanted =3D "WS2"; foreach (key; aa.byKey.filter!(k =3D> k !=3D strComputerIDunwanted)) {= writeln(key, ' ', aa[key]); } // 't' is the tuple of key and value foreach (t; aa.byKeyValue.filter!(t =3D> t.key !=3D strComputerIDunwan= ted)) { writeln(t.key, ' ', t.value); } } Ali
Jun 21 2021
parent someone <someone somewhere.com> writes:
On Monday, 21 June 2021 at 08:31:16 UTC, Ali Çehreli wrote:

 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);
   }
 }
Like 'em both, very flexible indeed, I think there are a couple of places I could implement this. Thanks for your good advice as usual Ali :) !
Jun 23 2021
prev sibling next sibling parent reply frame <frame86 live.com> writes:
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:

 ```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 ?
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.
Jun 21 2021
parent someone <someone somewhere.com> writes:
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 !
Jun 21 2021
prev sibling next sibling parent reply wjoe <invalid example.com> writes:
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:

 ```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 ?
something like this ? ``` D import std.array; import std.algorithm; udtComputers.byPair .filter!(p => p.key != strComputerIDunwanted) .each!( (p) { /* foreach body */ } ); ```
Jun 21 2021
parent someone <someone somewhere.com> writes:
On Monday, 21 June 2021 at 15:32:09 UTC, wjoe wrote:

 something like this ?

 ``` D
 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 !
Jun 21 2021
prev sibling parent reply Elronnd <elronnd elronnd.net> writes:
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.
Jun 21 2021
next sibling parent reply Steven Schveighoffer <schveiguy gmail.com> writes:
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
Jun 21 2021
parent someone <someone somewhere.com> writes:
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: ```d 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.
Jun 21 2021
prev sibling parent someone <someone somewhere.com> writes:
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
Jun 21 2021