Jump to page: 1 2
Thread overview
Task to throw away string parts, use joiner and splitter not very successful
Dec 31, 2013
Dfr
Dec 31, 2013
Chris Cain
Dec 31, 2013
Rémy Mouëza
Jan 01, 2014
Dfr
Jan 01, 2014
Rémy Mouëza
Jan 02, 2014
monarch_dodra
Jan 01, 2014
bearophile
Jan 02, 2014
monarch_dodra
Jan 01, 2014
Dfr
Jan 01, 2014
Rémy Mouëza
Jan 01, 2014
Dfr
Jan 02, 2014
monarch_dodra
Jan 02, 2014
monarch_dodra
December 31, 2013
Hello, i have string like "this.is.a.string" and want to throw away some parts separated by dots, here is first attempt:

name = "this.is.a.string"; // <-- want to make "this.is.a" from this
auto nameparts = splitter(name, '.');
auto name1 = joiner(nameparts[0 .. $-1], '.');

And got this error: "Error: Result cannot be sliced with []"

So, kinda fixed it (correct way?):

name = "this.is.a.string";
auto nameparts = splitter(name, '.').array;
auto name1 = joiner(nameparts[0 .. $-1], '.');

got this:

Error: template std.algorithm.joiner does not match any function template declaration. Candidates are:
/usr/include/dmd/phobos/std/algorithm.d(2846):        std.algorithm.joiner(RoR, Separator)(RoR r, Separator sep) if (isInputRange!RoR && isInputRange!(ElementType!RoR) && isForwardRange!Separator && is(ElementType!Separator : ElementType!(ElementType!RoR)))

Stuck here, thank you for any help.

December 31, 2013
On Tuesday, 31 December 2013 at 20:49:55 UTC, Dfr wrote:
> Hello, i have string like "this.is.a.string" and want to throw away some parts separated by dots, here is first attempt:
>
> name = "this.is.a.string"; // <-- want to make "this.is.a" from this
> auto nameparts = splitter(name, '.');
> auto name1 = joiner(nameparts[0 .. $-1], '.');
>
> And got this error: "Error: Result cannot be sliced with []"
>
> So, kinda fixed it (correct way?):
>
> name = "this.is.a.string";
> auto nameparts = splitter(name, '.').array;
> auto name1 = joiner(nameparts[0 .. $-1], '.');
>
> got this:
>
> Error: template std.algorithm.joiner does not match any function template declaration. Candidates are:
> /usr/include/dmd/phobos/std/algorithm.d(2846):        std.algorithm.joiner(RoR, Separator)(RoR r, Separator sep) if (isInputRange!RoR && isInputRange!(ElementType!RoR) && isForwardRange!Separator && is(ElementType!Separator : ElementType!(ElementType!RoR)))
>
> Stuck here, thank you for any help.

From your error message: isForwardRange!Separator

Your separator is a character, which isn't a forward range. Try this:
`auto name1 = joiner(nameparts[0 .. $-1], ".");`
December 31, 2013
As Chris wrote, using double quotes to use strings instead of char solves the typing issse.

I'd also suggest the following alternative, if you're going to discard a lot of last elements in your code:
    import std.stdio;
    import std.algorithm;
    import std.array;
    import std.range;

    /// Return seq without its last element.
    auto poppedBack (T) (T seq) if (isInputRange!T) {
        seq.popBack; // Discards the last element.
        return seq;
    }

    void main () {
        // Prints "this.is.a".
        "this.is.a.string"
            .splitter (".")
            .poppedBack
            .joiner (".")
            .array
            .writeln;
    }


On 12/31/2013 09:57 PM, Chris Cain wrote:
> On Tuesday, 31 December 2013 at 20:49:55 UTC, Dfr wrote:
>> Hello, i have string like "this.is.a.string" and want to throw away
>> some parts separated by dots, here is first attempt:
>>
>> name = "this.is.a.string"; // <-- want to make "this.is.a" from this
>> auto nameparts = splitter(name, '.');
>> auto name1 = joiner(nameparts[0 .. $-1], '.');
>>
>> And got this error: "Error: Result cannot be sliced with []"
>>
>> So, kinda fixed it (correct way?):
>>
>> name = "this.is.a.string";
>> auto nameparts = splitter(name, '.').array;
>> auto name1 = joiner(nameparts[0 .. $-1], '.');
>>
>> got this:
>>
>> Error: template std.algorithm.joiner does not match any function
>> template declaration. Candidates are:
>> /usr/include/dmd/phobos/std/algorithm.d(2846):
>> std.algorithm.joiner(RoR, Separator)(RoR r, Separator sep) if
>> (isInputRange!RoR && isInputRange!(ElementType!RoR) &&
>> isForwardRange!Separator && is(ElementType!Separator :
>> ElementType!(ElementType!RoR)))
>>
>> Stuck here, thank you for any help.
>
>  From your error message: isForwardRange!Separator
>
> Your separator is a character, which isn't a forward range. Try this:
> `auto name1 = joiner(nameparts[0 .. $-1], ".");`

January 01, 2014
Chris Cain:

> From your error message: isForwardRange!Separator
>
> Your separator is a character, which isn't a forward range. Try this:
> `auto name1 = joiner(nameparts[0 .. $-1], ".");`

But splitting on a char is a common operation, and isn't it more efficient than splitting on a string?

Bye,
bearophile
January 01, 2014
This is interesting, why i can't just do it simpler way ?

"this.is.a.string"
             .splitter (".")
             .popBack
             .joiner (".")
             .array
             .writeln;


Because creating an extra function is not desired.

> As Chris wrote, using double quotes to use strings instead of char solves the typing issse.
>
> I'd also suggest the following alternative, if you're going to discard a lot of last elements in your code:
>     import std.stdio;
>     import std.algorithm;
>     import std.array;
>     import std.range;
>
>     /// Return seq without its last element.
>     auto poppedBack (T) (T seq) if (isInputRange!T) {
>         seq.popBack; // Discards the last element.
>         return seq;
>     }
>
>     void main () {
>         // Prints "this.is.a".
>         "this.is.a.string"
>             .splitter (".")
>             .poppedBack
>             .joiner (".")
>             .array
>             .writeln;
>     }
>
>
> On 12/31/2013 09:57 PM, Chris Cain wrote:
>> On Tuesday, 31 December 2013 at 20:49:55 UTC, Dfr wrote:
>>> Hello, i have string like "this.is.a.string" and want to throw away
>>> some parts separated by dots, here is first attempt:
>>>
>>> name = "this.is.a.string"; // <-- want to make "this.is.a" from this
>>> auto nameparts = splitter(name, '.');
>>> auto name1 = joiner(nameparts[0 .. $-1], '.');
>>>
>>> And got this error: "Error: Result cannot be sliced with []"
>>>
>>> So, kinda fixed it (correct way?):
>>>
>>> name = "this.is.a.string";
>>> auto nameparts = splitter(name, '.').array;
>>> auto name1 = joiner(nameparts[0 .. $-1], '.');
>>>
>>> got this:
>>>
>>> Error: template std.algorithm.joiner does not match any function
>>> template declaration. Candidates are:
>>> /usr/include/dmd/phobos/std/algorithm.d(2846):
>>> std.algorithm.joiner(RoR, Separator)(RoR r, Separator sep) if
>>> (isInputRange!RoR && isInputRange!(ElementType!RoR) &&
>>> isForwardRange!Separator && is(ElementType!Separator :
>>> ElementType!(ElementType!RoR)))
>>>
>>> Stuck here, thank you for any help.
>>
>> From your error message: isForwardRange!Separator
>>
>> Your separator is a character, which isn't a forward range. Try this:
>> `auto name1 = joiner(nameparts[0 .. $-1], ".");`
January 01, 2014
And one more problem here:

    string name = "test";
    auto nameparts = splitter(name, '.');
    writeln(typeof(joiner(nameparts, ".").array).stringof);

This prints "dchar[]", but i need char[] or string, how to get my 'string' back ?


On Tuesday, 31 December 2013 at 20:49:55 UTC, Dfr wrote:
> Hello, i have string like "this.is.a.string" and want to throw away some parts separated by dots, here is first attempt:
>
> name = "this.is.a.string"; // <-- want to make "this.is.a" from this
> auto nameparts = splitter(name, '.');
> auto name1 = joiner(nameparts[0 .. $-1], '.');
>
> And got this error: "Error: Result cannot be sliced with []"
>
> So, kinda fixed it (correct way?):
>
> name = "this.is.a.string";
> auto nameparts = splitter(name, '.').array;
> auto name1 = joiner(nameparts[0 .. $-1], '.');
>
> got this:
>
> Error: template std.algorithm.joiner does not match any function template declaration. Candidates are:
> /usr/include/dmd/phobos/std/algorithm.d(2846):        std.algorithm.joiner(RoR, Separator)(RoR r, Separator sep) if (isInputRange!RoR && isInputRange!(ElementType!RoR) && isForwardRange!Separator && is(ElementType!Separator : ElementType!(ElementType!RoR)))
>
> Stuck here, thank you for any help.

January 01, 2014
The popBack function returns the element you are removing from the array, not the array itself, thus "breaking" the chaining of function.

On 01/01/2014 08:36 AM, Dfr wrote:
> This is interesting, why i can't just do it simpler way ?
>
> "this.is.a.string"
>               .splitter (".")
>               .popBack
>               .joiner (".")
>               .array
>               .writeln;
>
>
> Because creating an extra function is not desired.
>
>> As Chris wrote, using double quotes to use strings instead of char
>> solves the typing issse.
>>
>> I'd also suggest the following alternative, if you're going to discard
>> a lot of last elements in your code:
>>     import std.stdio;
>>     import std.algorithm;
>>     import std.array;
>>     import std.range;
>>
>>     /// Return seq without its last element.
>>     auto poppedBack (T) (T seq) if (isInputRange!T) {
>>         seq.popBack; // Discards the last element.
>>         return seq;
>>     }
>>
>>     void main () {
>>         // Prints "this.is.a".
>>         "this.is.a.string"
>>             .splitter (".")
>>             .poppedBack
>>             .joiner (".")
>>             .array
>>             .writeln;
>>     }
>>
>>
>> On 12/31/2013 09:57 PM, Chris Cain wrote:
>>> On Tuesday, 31 December 2013 at 20:49:55 UTC, Dfr wrote:
>>>> Hello, i have string like "this.is.a.string" and want to throw away
>>>> some parts separated by dots, here is first attempt:
>>>>
>>>> name = "this.is.a.string"; // <-- want to make "this.is.a" from this
>>>> auto nameparts = splitter(name, '.');
>>>> auto name1 = joiner(nameparts[0 .. $-1], '.');
>>>>
>>>> And got this error: "Error: Result cannot be sliced with []"
>>>>
>>>> So, kinda fixed it (correct way?):
>>>>
>>>> name = "this.is.a.string";
>>>> auto nameparts = splitter(name, '.').array;
>>>> auto name1 = joiner(nameparts[0 .. $-1], '.');
>>>>
>>>> got this:
>>>>
>>>> Error: template std.algorithm.joiner does not match any function
>>>> template declaration. Candidates are:
>>>> /usr/include/dmd/phobos/std/algorithm.d(2846):
>>>> std.algorithm.joiner(RoR, Separator)(RoR r, Separator sep) if
>>>> (isInputRange!RoR && isInputRange!(ElementType!RoR) &&
>>>> isForwardRange!Separator && is(ElementType!Separator :
>>>> ElementType!(ElementType!RoR)))
>>>>
>>>> Stuck here, thank you for any help.
>>>
>>> From your error message: isForwardRange!Separator
>>>
>>> Your separator is a character, which isn't a forward range. Try this:
>>> `auto name1 = joiner(nameparts[0 .. $-1], ".");`

January 01, 2014
You can use `std.conv.to` to convert the dchar[] back to a string, adding `.to!string` at the end of the dchar[] array you want to convert.

Also not that there exists two similar functions to the lazy evaluated splitter() and joiner() in std.array: the eagerly evaluated split() and join(); being eager make the code looks more straightforward (no `.array` or `.to!string`).

    import std.stdio;
    import std.array;
    import std.algorithm;

    void eager () {
        string name = "thiš.ìs.à.çtriñg";
        auto parts  = name.split (".");
        parts.popBack;
        auto cut    = parts.join (".");
        cut.writeln;
    }

    void lazy_ () {
        string name = "thiš.ìs.à.çtriñg";
        auto parts  = name.splitter (".");
        parts.popBack;
        auto cut    = parts.joiner (".").array.to!string;
        cut.writeln;
    }

    void main () {
        eager ();
        lazy_ ();
    }

The program prints:
thiš.ìs.à
thiš.ìs.à

On 01/01/2014 08:40 AM, Dfr wrote:
> And one more problem here:
>
>      string name = "test";
>      auto nameparts = splitter(name, '.');
>      writeln(typeof(joiner(nameparts, ".").array).stringof);
>
> This prints "dchar[]", but i need char[] or string, how to get my
> 'string' back ?
>
>
> On Tuesday, 31 December 2013 at 20:49:55 UTC, Dfr wrote:
>> Hello, i have string like "this.is.a.string" and want to throw away
>> some parts separated by dots, here is first attempt:
>>
>> name = "this.is.a.string"; // <-- want to make "this.is.a" from this
>> auto nameparts = splitter(name, '.');
>> auto name1 = joiner(nameparts[0 .. $-1], '.');
>>
>> And got this error: "Error: Result cannot be sliced with []"
>>
>> So, kinda fixed it (correct way?):
>>
>> name = "this.is.a.string";
>> auto nameparts = splitter(name, '.').array;
>> auto name1 = joiner(nameparts[0 .. $-1], '.');
>>
>> got this:
>>
>> Error: template std.algorithm.joiner does not match any function
>> template declaration. Candidates are:
>> /usr/include/dmd/phobos/std/algorithm.d(2846):
>> std.algorithm.joiner(RoR, Separator)(RoR r, Separator sep) if
>> (isInputRange!RoR && isInputRange!(ElementType!RoR) &&
>> isForwardRange!Separator && is(ElementType!Separator :
>> ElementType!(ElementType!RoR)))
>>
>> Stuck here, thank you for any help.
>

January 01, 2014
Thank you, very clear explained.

On Wednesday, 1 January 2014 at 16:31:43 UTC, Rémy Mouëza wrote:
> You can use `std.conv.to` to convert the dchar[] back to a string, adding `.to!string` at the end of the dchar[] array you want to convert.
>
> Also not that there exists two similar functions to the lazy evaluated splitter() and joiner() in std.array: the eagerly evaluated split() and join(); being eager make the code looks more straightforward (no `.array` or `.to!string`).
>
>     import std.stdio;
>     import std.array;
>     import std.algorithm;
>
>     void eager () {
>         string name = "thiš.ìs.à.çtriñg";
>         auto parts  = name.split (".");
>         parts.popBack;
>         auto cut    = parts.join (".");
>         cut.writeln;
>     }
>
>     void lazy_ () {
>         string name = "thiš.ìs.à.çtriñg";
>         auto parts  = name.splitter (".");
>         parts.popBack;
>         auto cut    = parts.joiner (".").array.to!string;
>         cut.writeln;
>     }
>
>     void main () {
>         eager ();
>         lazy_ ();
>     }
>
> The program prints:
> thiš.ìs.à
> thiš.ìs.à
>
> On 01/01/2014 08:40 AM, Dfr wrote:
>> And one more problem here:
>>
>>     string name = "test";
>>     auto nameparts = splitter(name, '.');
>>     writeln(typeof(joiner(nameparts, ".").array).stringof);
>>
>> This prints "dchar[]", but i need char[] or string, how to get my
>> 'string' back ?
>>
>>
>> On Tuesday, 31 December 2013 at 20:49:55 UTC, Dfr wrote:
>>> Hello, i have string like "this.is.a.string" and want to throw away
>>> some parts separated by dots, here is first attempt:
>>>
>>> name = "this.is.a.string"; // <-- want to make "this.is.a" from this
>>> auto nameparts = splitter(name, '.');
>>> auto name1 = joiner(nameparts[0 .. $-1], '.');
>>>
>>> And got this error: "Error: Result cannot be sliced with []"
>>>
>>> So, kinda fixed it (correct way?):
>>>
>>> name = "this.is.a.string";
>>> auto nameparts = splitter(name, '.').array;
>>> auto name1 = joiner(nameparts[0 .. $-1], '.');
>>>
>>> got this:
>>>
>>> Error: template std.algorithm.joiner does not match any function
>>> template declaration. Candidates are:
>>> /usr/include/dmd/phobos/std/algorithm.d(2846):
>>> std.algorithm.joiner(RoR, Separator)(RoR r, Separator sep) if
>>> (isInputRange!RoR && isInputRange!(ElementType!RoR) &&
>>> isForwardRange!Separator && is(ElementType!Separator :
>>> ElementType!(ElementType!RoR)))
>>>
>>> Stuck here, thank you for any help.

January 02, 2014
On Wednesday, 1 January 2014 at 00:19:39 UTC, bearophile wrote:
> Chris Cain:
>
>> From your error message: isForwardRange!Separator
>>
>> Your separator is a character, which isn't a forward range. Try this:
>> `auto name1 = joiner(nameparts[0 .. $-1], ".");`
>
> But splitting on a char is a common operation, and isn't it more efficient than splitting on a string?
>
> Bye,
> bearophile

The "separator" here is actually a joiner element. "splitter(range, '.')" *does* work.

AFAIK, there should be no problem providing a "joiner(RoR, E)". I think it's on my "todo".

I think the "issue" was that the overload *may* have been ambiguous...? I'll have to double check.
« First   ‹ Prev
1 2