Thread overview | |||||||
---|---|---|---|---|---|---|---|
|
June 01, 2015 Splitting a range into a range of tuples | ||||
---|---|---|---|---|
| ||||
Hi, I have a string of pairs of integers, where pairs are delimited from each other by commas, and members of the pair are delimited by a space. I'd like to end up with something like a range of 2-tuples, which I can then sort with a lambda. I'm running into problems trying to do this, after splitting on commas: Tuple!(int,int) coord = to!(int[])(splitter(pairString," ").array[]); ...which may not even be a good idea, I don't know. I've been following D for a long time, but this is the first time I've tried to actually use it; this seems like the kind of thing that should take just a few lines, if only I knew the libraries and range concepts well enough. To be clear, this is what I have: "192 14, 301 3, 578 0, 0 17" ...and this is what I want: [(578,0),(301,3),(192,14),(0,17)] What's the best way to do this? Should I be using map!() somewhere? Thanks, Adam |
June 01, 2015 Re: Splitting a range into a range of tuples | ||||
---|---|---|---|---|
| ||||
Posted in reply to Adam | On 06/01/2015 03:31 PM, Adam wrote: > Hi, > > I have a string of pairs of integers, where pairs are delimited from > each other by commas, and members of the pair are delimited by a space. > I'd like to end up with something like a range of 2-tuples, which I can > then sort with a lambda. I'm running into problems trying to do this, > after splitting on commas: > > Tuple!(int,int) coord = to!(int[])(splitter(pairString," ").array[]); > > ...which may not even be a good idea, I don't know. I've been following > D for a long time, but this is the first time I've tried to actually use > it; this seems like the kind of thing that should take just a few lines, > if only I knew the libraries and range concepts well enough. > > To be clear, this is what I have: > > "192 14, 301 3, 578 0, 0 17" > > ...and this is what I want: > > [(578,0),(301,3),(192,14),(0,17)] > > What's the best way to do this? Should I be using map!() somewhere? > > Thanks, > Adam With no promises on performance and with a bonus mind-blowing format string... :) I am sure it can be improved a lot. import std.stdio; import std.algorithm; import std.range; import std.conv; void main() { auto input = "192 14, 301 3, 578 0, 0 17"; auto result = input .splitter(',') .map!splitter .joiner .map!(to!int) .chunks(2) .map!array .array .sort() .retro; writeln(result); writefln("[%((%(%s,%))%|,%)]", result); } Prints both an array of arrays and the same format that you wanted: [[578, 0], [301, 3], [192, 14], [0, 17]] [(578,0),(301,3),(192,14),(0,17)] Ali |
June 01, 2015 Re: Splitting a range into a range of tuples | ||||
---|---|---|---|---|
| ||||
Posted in reply to Adam | On Monday, 1 June 2015 at 22:31:38 UTC, Adam wrote:
> Hi,
>
> I have a string of pairs of integers, where pairs are delimited from each other by commas, and members of the pair are delimited by a space. I'd like to end up with something like a range of 2-tuples
I can offer this option:
import std.stdio, std.algorithm, std.array, std.range, std.format, std.typecons;
void main() {
string s = "192 14, 301 3, 578 0, 0 17";
int[] arr; int tmp;
foreach (el; s.split) {
formattedRead(el, "%s", &tmp);
arr ~= tmp;
}
Tuple!(int, int)[] tup;
foreach (el; zip(arr.stride(2), arr.dropOne.stride(2))) {
tup ~= tuple(el[0], el[1]);
}
tup.sort!"a[0] > b[0]";
writeln(tup);
}
/*[Tuple!(int, int)(578, 0), Tuple!(int, int)(301, 3), Tuple!(int, int)(192, 14), Tuple!(int, int)(0, 17)]*/
|
June 02, 2015 Re: Splitting a range into a range of tuples | ||||
---|---|---|---|---|
| ||||
Posted in reply to Ali Çehreli | > auto result = input > .splitter(',') > .map!splitter > .joiner > .map!(to!int) > .chunks(2) > .map!array > .array > .sort() > .retro; > Thanks for the reply. I'm a bit confused by the splitter followed immediately by the joiner...and then it kinda falls apart for me. Here's where I've ended up: auto result = input .splitter(",") // range of strings .map!(v => v.splitter(" ") // range of ranges strings .array // range of arrays of strings .to!(int[])) // range of arrays of ints .Tuple!(int,int); Everything is fine until I try to instantiate Tuples with my arrays. Then I get an error that says none of the overloads of the constructor are callable with these arguments. But I see this: http://dlang.org/phobos/std_typecons.html#.Tuple.this.2 , which makes me think it should work. Am I doing something wrong? |
June 02, 2015 Re: Splitting a range into a range of tuples | ||||
---|---|---|---|---|
| ||||
Posted in reply to Adam |
> Everything is fine until I try to instantiate Tuples with my arrays. Then I get an error that says none of the overloads of the constructor are callable with these arguments. But I see this: http://dlang.org/phobos/std_typecons.html#.Tuple.this.2 , which makes me think it should work. Am I doing something wrong?
Alright! I got what I wanted. Posting here for any fellow noobs who may stumble across this and care what I was screwing up. It looks like I accidentally gave a bad example, because I needed to sort on the second elements ascending, not the first elements descending. The lambdas I was feeding to sort were not working because of the crazy types coming from the range methods, and it turns out that I did not need tuples, since I could get a proper sort from an array. This is what I ended up with (plus a couple of filters that I'm omitting for clarity):
auto result =
input
.splitter(",")
.map!(v => v.splitter(" ")
.map!(a => a.to!(int))
.array()
)
.array()
.sort!("a[1]<b[1]");
Thanks Ali and Dennis for taking time to respond.
|
Copyright © 1999-2021 by the D Language Foundation