January 19, 2014 Re: Better idea for double list comprehension? | ||||
---|---|---|---|---|
| ||||
Posted in reply to CJS | On Sunday, 19 January 2014 at 02:10:01 UTC, CJS wrote: > That's more concise but I also think it's more confusing. I assume that to!string is doing the exact same thing, but I was hoping for something to do the appropriate implicit conversations. Especially to a range of length 1, though I can understand that kind of auto-magical conversion would be annoying in a number of important instances. Does not compute. You mean implicit conversion of single character to a range? > I changed the code to this: > > import std.stdio : writeln; > import std.range : chunks, chain; > import std.algorithm; > import std.array; > import std.conv; > > auto cross(R1, R2)(R1 A, R2 B) { > return cartesianProduct(A, B).map!(ab => ab[].text).array; > } > > > void main(){ > const string letters = "ABCDEFGHI"; > const string digits = "123456789"; > > auto cols = digits; > auto rows = letters; > > auto squares = cross(rows, cols); > string[][] unitlist; You may want to use an appender here. It's more efficient than ~= , and lets you transform those foreach loops into one-liners :) auto app = appender(&unitlist); /+ foreach(c; cols){ unitlist ~= cross(rows, to!string(c)); } foreach(r; rows){ unitlist ~= cross(to!string(r), cols); } foreach(r; chunks(rows, 3)){ foreach(c; chunks(cols, 3)){ unitlist ~= cross(to!string(r),to!string(c)); } } +/ app.put(cols.map!(x => cross(rows, x.text))); app.put(rows.map!(x => cross(x.text, cols))); app.put(chunks(rows,3).map!(r => chunks(cols,3).map!(c => cross(r.text, c.text)))); > string[][][string] units; > string[][string] peers; > > foreach(s; squares){ > units[s] = unitlist.filter!(x => any!(y => s==y)); \\line 37 > } This one seems like it should be unitlist.filter!(x => x.any!(y => s==y)).array(); > foreach(s; squares){ > peers[s] = remove(chain(units[s]), s); \\line 41 > } This one I don't understand. chain(units[s]) ? That's the same as units[s]. remove() returns a range, in this case string[][]. |
January 19, 2014 Re: Better idea for double list comprehension? | ||||
---|---|---|---|---|
| ||||
Posted in reply to Stanislav Blinov | Thanks! > > auto app = appender(&unitlist); > Ah, I'd been wondering if there was something like this. But why does it need unitlist's address? (Assume & has the same meaning as in C and C++.) > > This one seems like it should be unitlist.filter!(x => x.any!(y => s==y)).array(); > Oh. Duh. But what is the .array() at the end doing? Allocating a new array for the results of the filter, since it's basically just a lazily computed range rather than actual storage for the results? >> foreach(s; squares){ >> peers[s] = remove(chain(units[s]), s); \\line 41 >> } > > This one I don't understand. chain(units[s]) ? That's the same as units[s]. remove() returns a range, in this case string[][]. I'm just trying to match what the python code was doing. In that case the line peers = dict((s, set(sum(units[s],[]))-set([s])) for s in squares) was using sum to concatenate a bunch of lists together and then remove the element. But I miscounted the parentheses and didn't notice the '-' was after the concatenated lists were tured into a set. The following code appears to do what I want, but the string temporary and appender are a bit ugly. Any suggestions on getting rid of them? foreach(s; squares){ string[] tmp; auto app2 = appender(&tmp); foreach(t; units[s]) {app2.put(t);} peers[s] = tmp.sort().uniq().filter!(a => a!=s).array(); } |
January 19, 2014 Re: Better idea for double list comprehension? | ||||
---|---|---|---|---|
| ||||
Posted in reply to CJS | On Sunday, 19 January 2014 at 06:57:37 UTC, CJS wrote: > Ah, I'd been wondering if there was something like this. But why does it need unitlist's address? (Assume & has the same meaning as in C and C++.) Look at the docs for Appender. It can either provide its own storage, or use an existing one. In the latter case you feed it a pointer to your array and it uses that. > >> >> This one seems like it should be unitlist.filter!(x => x.any!(y => s==y)).array(); >> > > Oh. Duh. But what is the .array() at the end doing? Allocating a new array for the results of the filter, since it's basically just a lazily computed range rather than actual storage for the results? Yes. But in this case you'd have to allocate anyways, to fill the units[s] array. > I'm just trying to match what the python code was doing. In that case the line Ah, I see. > > peers = dict((s, set(sum(units[s],[]))-set([s])) > for s in squares) > > was using sum to concatenate a bunch of lists together and then remove the element. But I miscounted the parentheses and didn't notice the '-' was after the concatenated lists were tured into a set. The following code appears to do what I want, but the string temporary and appender are a bit ugly. Any suggestions on getting rid of them? > foreach(s; squares){ peers[s] = units[s].join().sort().uniq().filter!(a => a!=s).array(); } That's std.array.join() there. However, I notice that the output (the order of elements) differs from the one on that page you linked earlier. |
January 19, 2014 Re: Better idea for double list comprehension? | ||||
---|---|---|---|---|
| ||||
Posted in reply to Stanislav Blinov |
>
> That's std.array.join() there. However, I notice that the output (the order of elements) differs from the one on that page you linked earlier.
The order shouldn't be a problem. Join is a great idea. I'd thought it was only for an array of strings. Thanks for all the help!
|
Copyright © 1999-2021 by the D Language Foundation