digitalmars.D.learn - foreach automoatic counter?
- French Football (15/15) Sep 21 2015 Going through a book on coding in D,
- Justin Whear (5/21) Sep 21 2015 With an associative array the foreach becomes:
- French Football (8/9) Sep 21 2015 Thankyou! .enumerate lets me iterate over a container with a
- cym13 (28/39) Sep 21 2015 I had to look into phobos sources
- French Football (3/11) Sep 21 2015 Thankyou!
- cym13 (5/18) Sep 21 2015 Such a unittest should normally be automatically included in
- cym13 (33/48) Sep 21 2015 That's because this isn't really a counter. It makes more sens if
- Jonathan M Davis via Digitalmars-d-learn (20/35) Sep 21 2015 It's an index, not a counter. In the case of an array, it's what's used ...
- Steven Schveighoffer (3/7) Sep 22 2015 As Justin Whear pointed out, enumerate is better when you have one range...
Going through a book on coding in D, http://ddili.org/ders/d.en/foreach.html , I find the following very useful feature: When two names are specified in the names section [with a plain array], they represent an automatic counter and the value of the element, respectively: foreach (i, element; array) { writeln(i, ": ", element); } I understand that foreach is built on top of a for loop... I'm just wondering why I can't access the automatic counter from a doubly linked list, or an associative array, or some range? It's pretty common for me to have to rewrite foreach loops to be for loops when I get to the bottom and realize I need to know where in the sequence I am...
Sep 21 2015
On Mon, 21 Sep 2015 15:38:38 +0000, French Football wrote:Going through a book on coding in D, http://ddili.org/ders/d.en/foreach.html , I find the following very useful feature: When two names are specified in the names section [with a plain array], they represent an automatic counter and the value of the element, respectively: foreach (i, element; array) { writeln(i, ": ", element); } I understand that foreach is built on top of a for loop... I'm just wondering why I can't access the automatic counter from a doubly linked list, or an associative array, or some range? It's pretty common for me to have to rewrite foreach loops to be for loops when I get to the bottom and realize I need to know where in the sequence I am...With an associative array the foreach becomes: foreach (key, value; aa) For arbitrary ranges you can use std.range.enumerate like this: foreach (i, element; someRange.enumerate)
Sep 21 2015
On Monday, 21 September 2015 at 15:54:06 UTC, Justin Whear wrote:On Monday, 21 September 2015 at 15:58:12 UTC, cym13 wrote:Thankyou! .enumerate lets me iterate over a container with a counter. --Related tangential question... If I have a DList, how do I insert into the middle of it? I'm trying .insertAfter but it wants a range and apparently I can only slice an entire Dlist with [].
Sep 21 2015
On Monday, 21 September 2015 at 16:32:25 UTC, French Football wrote:On Monday, 21 September 2015 at 15:54:06 UTC, Justin Whear wrote:I had to look into phobos sources (/usr/include/dlang/dmd/std/containers/dlist.d) to find a unittest, and judging from it it seems inserting in the middle of a DList just wasn't taken seriously. safe unittest { import std.algorithm : equal; auto dl = DList!string(["a", "b", "d"]); dl.insertAfter(dl[], "e"); // insert at the end assert(equal(dl[], ["a", "b", "d", "e"])); auto dlr = dl[]; dlr.popBack(); dlr.popBack(); dl.insertAfter(dlr, "c"); // insert after "b" assert(equal(dl[], ["a", "b", "c", "d", "e"])); } There is however a nicer method using std.ranges: void main(string[] args) { import std.stdio; import std.range; import std.container: DList; auto list = DList!int([1, 2, 3, 5]); list.insertBefore(list[].drop(3), 4); foreach(n ; list) writeln(n); } I hope this is helpful.On Monday, 21 September 2015 at 15:58:12 UTC, cym13 wrote:Thankyou! .enumerate lets me iterate over a container with a counter. --Related tangential question... If I have a DList, how do I insert into the middle of it? I'm trying .insertAfter but it wants a range and apparently I can only slice an entire Dlist with [].
Sep 21 2015
On Monday, 21 September 2015 at 19:23:38 UTC, cym13 wrote:On Monday, 21 September 2015 at 16:32:25 UTC, French Football wrote:Thankyou! But wow... talk about pulling teeth...[...]I had to look into phobos sources (/usr/include/dlang/dmd/std/containers/dlist.d) to find a unittest, and judging from it it seems inserting in the middle of a DList just wasn't taken seriously. [...]
Sep 21 2015
On Monday, 21 September 2015 at 22:24:22 UTC, French Football wrote:On Monday, 21 September 2015 at 19:23:38 UTC, cym13 wrote:Such a unittest should normally be automatically included in online documentation when generating it, I don't know they were an exception...On Monday, 21 September 2015 at 16:32:25 UTC, French Football wrote:Thankyou! But wow... talk about pulling teeth...[...]I had to look into phobos sources (/usr/include/dlang/dmd/std/containers/dlist.d) to find a unittest, and judging from it it seems inserting in the middle of a DList just wasn't taken seriously. [...]
Sep 21 2015
On Monday, 21 September 2015 at 15:38:40 UTC, French Football wrote:Going through a book on coding in D, http://ddili.org/ders/d.en/foreach.html , I find the following very useful feature: When two names are specified in the names section [with a plain array], they represent an automatic counter and the value of the element, respectively: foreach (i, element; array) { writeln(i, ": ", element); } I understand that foreach is built on top of a for loop... I'm just wondering why I can't access the automatic counter from a doubly linked list, or an associative array, or some range? It's pretty common for me to have to rewrite foreach loops to be for loops when I get to the bottom and realize I need to know where in the sequence I am...That's because this isn't really a counter. It makes more sens if you think of it as: foreach (key, value ; array) { ... } In the case of an array, the key to access directly a value is its index, and the array is read in its natural order so the 'key' part acts as a counter. If array is an associative array instead of an array, then you get the key and value as well. If you want a counter, you want to look at std.range.enumerate() which takes a range and returns a tuple (counter, element). The following example demonstrates the two usages with associative arrays: void main(string[] args) { import std.stdio; import std.range; bool[int] aa = [0:true, 1:true, 2:false]; writeln("Get keys and values from an AA"); foreach (key, value ; aa) { writeln(key, ": ", value); } writeln; writeln("Get a counter and the key of an AA"); foreach (count, key ; aa.byKey.enumerate) { writeln("count: ", count, " key: ", key, " value: ", aa[key]); } } Note that contrary to languages such as PHP, D's associative arrays are unordered so you can't use this counter as an index.
Sep 21 2015
On Monday, September 21, 2015 15:38:38 French Football via Digitalmars-d-learn wrote:Going through a book on coding in D, http://ddili.org/ders/d.en/foreach.html , I find the following very useful feature: When two names are specified in the names section [with a plain array], they represent an automatic counter and the value of the element, respectively: foreach (i, element; array) { writeln(i, ": ", element); } I understand that foreach is built on top of a for loop... I'm just wondering why I can't access the automatic counter from a doubly linked list, or an associative array, or some range? It's pretty common for me to have to rewrite foreach loops to be for loops when I get to the bottom and realize I need to know where in the sequence I am...It's an index, not a counter. In the case of an array, it's what's used to access each element. In the case of an AA, it has no index. It's a set of unordered key-value pairs. So, if you did foreach(i, element; aa) {} what you're really getting is the key and value, not an index and its corresponding element. foreach(key, value; aa) {} would make more sense in that case, but it's merely a change in name. The types and what they represent are the same regardless. In the case of an input range, it doesn't have any kind of index. It's just a list of elements that keep getting popped off in order to iterate through them. And whether any kind of index would even make sense would depend on what the range represents. In the cases where it would make sense, the range is probably a random-access range, in which case, you can use indices explicitly if you want. In general though, if you want a counter for the range that you're indexing, then you can use lockstep to wrap the range, and then when you use it in foreach, you get the count and the element: - Jonathan M Davis
Sep 21 2015
On 9/21/15 6:49 PM, Jonathan M Davis via Digitalmars-d-learn wrote:In general though, if you want a counter for the range that you're indexing, then you can use lockstep to wrap the range, and then when you use it in foreach, you get the count and the element:As Justin Whear pointed out, enumerate is better when you have one range. -Steve
Sep 22 2015