On 3/3/22 04:14, BoQsc wrote:
> and if it contains integers, remove all the regular string characters.
Others assumed you wanted integer values but I think you want the digits
of the integers. It took me a while to realize that chunkBy can do that:
// Convenience functions to tuple members of the result
// of chunkBy when used with a unary predicate.
auto isMatched(T)(T tuple) {
return tuple[0];
}
// Ditto
auto chunkOf(T)(T tuple) {
return tuple[1];
}
auto numbers(R)(R range) {
import std.algorithm : chunkBy, filter, map;
import std.uni : isNumber;
return range
.chunkBy!isNumber
.filter!isMatched
.map!chunkOf;
}
unittest {
import std.algorithm : equal, map;
import std.conv : text;
// "٤٢" is a non-ASCII number example.
auto r = "123 ab ٤٢ c 456 xyz 789".numbers;
assert(r.map!text.equal(["123", "٤٢", "456", "789"]));
}
void main() {
}
isMatched() and chunkOf() are not necessary at all. I wanted to use
readable names to fields of the elements of chunkBy instead of the
cryptic t[0] and t[1]:
return range
.chunkBy!isNumber
.filter!(t => t[0]) // Not pretty
.map!(t => t[1]); // Not pretty
Those functions could not be nested functions because otherwise I would
have to write e.g.
return range
.chunkBy!isNumber
.filter!(t => isMatched(t)) // Not pretty
.map!(t => chunkOf(t)); // Not pretty
To get integer values, .to!int would work as long as the numbers consist
of ASCII digits. (I am removing ٤٢.)
import std.stdio;
import std.algorithm;
import std.conv;
writeln("123 abc 456 xyz 789".numbers.map!(to!int));
Ali