Thread overview | ||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|
|
February 28, 2013 Re: Make a hash out of two ranges | ||||
---|---|---|---|---|
| ||||
On 2/28/13, Andrej Mitrovic <andrej.mitrovich@gmail.com> wrote:
> import std.algorithm;
> import std.range;
>
> void main()
> {
> auto r = map!((a, b) => [a : b])(["foo"], ["bar"]); // error
> assert(r.front == ["foo" : "bar"]);
> }
>
> This doesn't compile, what am I missing?
>
A more clearer example:
void main()
{
auto r = map!((a, b) => [a : b])([1, 3], [2, 4]);
assert(r[0] == [1 : 2]);
assert(r[1] == [3 : 4]);
}
|
February 28, 2013 Re: Make a hash out of two ranges | ||||
---|---|---|---|---|
| ||||
On Thursday, February 28, 2013 04:56:48 Andrej Mitrovic wrote:
> import std.algorithm;
> import std.range;
>
> void main()
> {
> auto r = map!((a, b) => [a : b])(["foo"], ["bar"]); // error
> assert(r.front == ["foo" : "bar"]);
> }
>
> This doesn't compile, what am I missing?
Map only works on one range. You can't pass it two of them at the same time. You'd need to wrap them in a single range of pairs with something like zip.
- Jonathan M Davis
|
February 28, 2013 Re: Make a hash out of two ranges | ||||
---|---|---|---|---|
| ||||
Posted in reply to Andrej Mitrovic | Andrej Mitrovic: >> This doesn't compile, what am I missing? See: http://dlang.org/phobos/std_array.html#.assocArray |
February 28, 2013 Re: Make a hash out of two ranges | ||||
---|---|---|---|---|
| ||||
Posted in reply to Andrej Mitrovic | On Thursday, 28 February 2013 at 03:59:16 UTC, Andrej Mitrovic wrote: > void main() > { > auto r = map!((a, b) => [a : b])([1, 3], [2, 4]); > assert(r[0] == [1 : 2]); > assert(r[1] == [3 : 4]); > } Map in std.algorithm doesn't really work like that. Many languages use "map" to mean hashing items, but "map" in functional programming (and D) really means something more like "apply this function to each item." So, if you did something like this: auto arr = [1,3]; auto r = map!(a => a + 1)(arr); assert(r[0] == 2); // because arr[0] + 1 == 2 ... f(arr[0]) = f(1) = 1 + 1 = 2 assert(r[1] == 4); // because arr[1] + 1 == 4 ... f(arr[1]) = f(3) = 3 + 1 = 4 Then you'd have the correct idea. If you're trying to create an associative array from two arrays, zip and associative arrays could be handy: http://dlang.org/phobos/std_range.html#.zip http://dlang.org/hash-map.html So, you could use it like so... int[int] aa; foreach(a, b; zip([1,3], [2,4])) aa[a] = b; writeln(aa); // prints [1:2, 3:4] |
February 28, 2013 Re: Make a hash out of two ranges | ||||
---|---|---|---|---|
| ||||
On 2/28/13, Jonathan M Davis <jmdavisProg@gmx.com> wrote:
> You'd need to wrap them in a single range of pairs with something like zip.
I'm not exactly sure how to do that though. Just using zip in the argument place won't work.
I've tried to create my own range, but I'm having issues:
import std.string;
import std.stdio;
import std.range;
auto mymap(alias func, Ranges...)(Ranges ranges)
{
static struct MyMap
{
Ranges ranges;
@property bool empty()
{
foreach (ref range; ranges)
if (range.empty)
return true;
return false;
}
@property auto front()
{
static string getMixin()
{
string[] args;
foreach (idx; 0 .. Ranges.length)
args ~= format("ranges[%s].front", idx);
return args.join(", ");
}
mixin(format(q{
return func(%s);
}, getMixin()));
}
void popFront()
{
foreach (ref range; ranges)
range.popFront();
}
}
return MyMap(ranges);
}
void main()
{
auto r = mymap!((a, b) => [a : b])([1, 3], [2, 4]);
writeln(r.front); // [1:2]
r.popFront();
writeln(r.front); // [3:4]
r.popFront();
// writeln(r.front); // this would throw as expected
auto r2 = mymap!((a, b) => [a : b])([1, 3], [2, 4]);
foreach (x; r2)
writeln(r2); // prints "[[1:2], [3:4]]" twice, why?
}
|
February 28, 2013 Re: Make a hash out of two ranges | ||||
---|---|---|---|---|
| ||||
On 2/28/13, Andrej Mitrovic <andrej.mitrovich@gmail.com> wrote:
> foreach (x; r2)
> writeln(r2); // prints "[[1:2], [3:4]]" twice, why?
Oh dumb me I'm priting r2 instead of x, my bad.
|
February 28, 2013 Re: Make a hash out of two ranges | ||||
---|---|---|---|---|
| ||||
Posted in reply to Chris Cain | On 2/28/13, Chris Cain <clcain@uncg.edu> wrote: > Map in std.algorithm doesn't really work like that. Many languages use "map" to mean hashing items, but "map" in functional programming (and D) really means something more like "apply this function to each item." I know that, I was expecting it to work with multiple ranges if the functor takes multiple arguments. > If you're trying to create an associative array from two arrays A *lazy* range of associative arrays. On 2/28/13, bearophile <bearophileHUGS@lycos.com> wrote: > See: > http://dlang.org/phobos/std_array.html#.assocArray Same answer as above. My custom range implementation shows exactly what I was trying to use map for. It only seems natural to me to have this ability, but maybe map!() can't be customized for this use. Anyway I'm satisfied with my approach unless you can make map!() do the same thing with some zip tricks or something. |
February 28, 2013 Re: Make a hash out of two ranges | ||||
---|---|---|---|---|
| ||||
Posted in reply to Andrej Mitrovic | On Thursday, 28 February 2013 at 04:50:34 UTC, Andrej Mitrovic wrote:
> On 2/28/13, Chris Cain <clcain@uncg.edu> wrote:
>> Map in std.algorithm doesn't really work like that. Many
>> languages use "map" to mean hashing items, but "map" in
>> functional programming (and D) really means something more like
>> "apply this function to each item."
>
> I know that, I was expecting it to work with multiple ranges if the
> functor takes multiple arguments.
>
>> If you're trying to create an associative array from two arrays
>
> A *lazy* range of associative arrays.
>
Aha, I see now. Here you go:
zip([1,3], [2,4])
.map!(e => [e[0] : e[1]])()
.writeln();
zip gives out a tuple, so I wish it were possible to do
.map!((a,b) => [a : b])()
instead and have it appropriately use the elements of the tuple. Maybe that'd be a potential enhancement possibility for map?
|
February 28, 2013 Re: Make a hash out of two ranges | ||||
---|---|---|---|---|
| ||||
Posted in reply to Chris Cain | On 2/28/13, Chris Cain <clcain@uncg.edu> wrote:
> Aha, I see now. Here you go:
>
> zip([1,3], [2,4])
> .map!(e => [e[0] : e[1]])()
> .writeln();
Thanks, I figured this out too by now. :)
But it's definitely nicer having the a/b syntax. I guess I could just overload my map against the phobos map.
|
February 28, 2013 Re: Make a hash out of two ranges | ||||
---|---|---|---|---|
| ||||
On Thu, Feb 28, 2013 at 4:14 PM, Andrej Mitrovic <andrej.mitrovich@gmail.com> wrote: > On 2/28/13, Chris Cain <clcain@uncg.edu> wrote: >> Aha, I see now. Here you go: >> >> zip([1,3], [2,4]) >> .map!(e => [e[0] : e[1]])() >> .writeln(); > > Thanks, I figured this out too by now. :) > > But it's definitely nicer having the a/b syntax. I guess I could just overload my map against the phobos map. Oh, that must be one of the first thing I coded in D, like, 4 years ago :) Multi-range map + filter + reduce. Here it is: https://github.com/PhilippeSigaud/dranges/blob/master/algorithm.d#L176 Ah, good times :) That must be much easier now, since Phobos and DMD are quite better. |
Copyright © 1999-2021 by the D Language Foundation