digitalmars.D.learn - Converting from DirIterator to string[] without a loop
- Dave Chapman (48/48) Jan 13 2017 I would like to do something like the code shown below but I
- =?UTF-8?Q?Ali_=c3=87ehreli?= (30/36) Jan 13 2017 The solution for that case is to use std.range.choose:
- Dave Chapman (20/63) Jan 14 2017 Thank you very much.
I would like to do something like the code shown below but I can't figure out how to do it without loops inside the if statement. When I use auto and print out the type of b it is something like args.main.FilterResult!(__lambda2, DirIterator).FilterResult and for the "if" version of b and args.main.FilterResult!(__lambda3, DirIterator).FilterResult for the "else" version so they are really different types. I have tried making b an array of DirEntry and an array of strings but that doesn't compile. Both expressions for b compile and run. I can put a foreach loop inside the if statement and convert b to an array of strings but that seems clumsy and not idiomatic D. Is there a way to do this without the conversion loop inside both branches of the if - else stament? Is there a way to use to!string or cast? // Is it possible to make this work? theResultType b; if (some_contition) { b = dirEntries("directory", SpanMode.shallow).filter!(f => (f.name == "file_name.txt") ); } else { b = dirEntries("directory", SpanMode.shallow).filter!(f => (f.name.endsWith(".d") )' } foreach(file; b) { do some stuff } // This works but seems clumsy and not idiomatic D string[] c = ""; if (some_contition) { auto b = dirEntries("directory", SpanMode.shallow).filter!(f => (f.name == "file_name.txt") ); foreach (file; b) { c = c ~ file; } } else { auto b = dirEntries("directory", SpanMode.shallow).filter!(f => (f.name.endsWith(".d") )' foreach (file; a) { c = c ~ file; } } foreach(file; c) { do some stuff }
Jan 13 2017
On 01/13/2017 04:29 PM, Dave Chapman wrote:When I use auto and print out the type of b it is something like args.main.FilterResult!(__lambda2, DirIterator).FilterResult and for the "if" version of b and args.main.FilterResult!(__lambda3, DirIterator).FilterResult for the "else" version so they are really different types.The solution for that case is to use std.range.choose: auto b = choose(some_condition, all.filter!(f => baseName(f.name) == "file_name.txt"), all.filter!(f => (f.name.endsWith(".d") ))); but I get the following error with DMD64 D Compiler v2.072.1: Error: no property '__postblit' for type 'FilterResult!(__lambda2, DirIterator)', did you mean '__xpostblit'? So, I put .array after both expressions below. The idiomatic way for what you're looking for is std.array.array (which is also exposed through std.range): import std.stdio; import std.file; import std.algorithm; import std.range; import std.path; void main(string[] args) { bool some_condition = (args.length > 1) && (args[1] == "foo"); auto all = dirEntries("directory", SpanMode.shallow); auto b = choose(some_condition, all.filter!(f => baseName(f.name) == "file_name.txt").array, all.filter!(f => (f.name.endsWith(".d") )).array); writeln(b); } However, in most cases keeping 'b' as a lazy algorithm is sufficient. Unless you really need an array e.g. for sorting, you can use std.algorithm.each (or map, etc.). (Not applicable in this case because of the error I mentioned above.) Ali
Jan 13 2017
On Saturday, 14 January 2017 at 01:02:38 UTC, Ali Çehreli wrote:On 01/13/2017 04:29 PM, Dave Chapman wrote:Thank you very much. I had a little trouble getting it working. It was acting as if both halves of the "choose" expression were always getting executed and the first half was making the contents of "all" empty and so the array b was always empty if I used the second half of the choose statement. I made a second copy of "all" and used it in the second half of the choose statement and then it worked. Like this: auto all = dirEntries("directory", SpanMode.shallow); auto all_2 = dirEntries("directory", SpanMode.shallow); auto b = choose(some_condition, all.filter!(f => (baseName(f.name) == requested_file)).array, all_2.filter!(f => (f.name.endsWith(".html") )).array); Note that I am really using requested_file instead of "file_name.txt" and ".html" instead of ".d" which is different than what I told you before just in case that matters. I am using Mac OS X 10.11.5 and dmd version 2.072.2 Thanks again for the help, DaveWhen I use auto and print out the type of b it is somethinglikeargs.main.FilterResult!(__lambda2, DirIterator).FilterResultand for the"if" version of b and args.main.FilterResult!(__lambda3,DirIterator).FilterResult forthe "else" version so they are really different types.The solution for that case is to use std.range.choose: auto b = choose(some_condition, all.filter!(f => baseName(f.name) == "file_name.txt"), all.filter!(f => (f.name.endsWith(".d") ))); but I get the following error with DMD64 D Compiler v2.072.1: Error: no property '__postblit' for type 'FilterResult!(__lambda2, DirIterator)', did you mean '__xpostblit'? So, I put .array after both expressions below. The idiomatic way for what you're looking for is std.array.array (which is also exposed through std.range): import std.stdio; import std.file; import std.algorithm; import std.range; import std.path; void main(string[] args) { bool some_condition = (args.length > 1) && (args[1] == "foo"); auto all = dirEntries("directory", SpanMode.shallow); auto b = choose(some_condition, all.filter!(f => baseName(f.name) == "file_name.txt").array, all.filter!(f => (f.name.endsWith(".d") )).array); writeln(b); } However, in most cases keeping 'b' as a lazy algorithm is sufficient. Unless you really need an array e.g. for sorting, you can use std.algorithm.each (or map, etc.). (Not applicable in this case because of the error I mentioned above.) Ali
Jan 14 2017