Jump to page: 1 2
Thread overview
Can you read the next line while iterating over byLine?
Feb 02, 2017
John Doe
Feb 02, 2017
Daniel Kozak
Feb 02, 2017
Daniel Kozak
Feb 02, 2017
Jack Stouffer
Feb 02, 2017
Daniel Kozak
Feb 02, 2017
John Doe
Feb 02, 2017
Daniel Kozak
Feb 02, 2017
John Doe
Feb 03, 2017
Daniel Kozak
Feb 04, 2017
Ivan Kazmenko
Feb 04, 2017
Mike Parker
Feb 02, 2017
Daniel Kozak
Feb 02, 2017
Ali Çehreli
February 02, 2017
Let's say you're trying to parse a file format like:

Name
http://example.com
123234

Foo Bar
http://dlang.org
888888

with blocks separated by varying amount of blank lines.

-----
import std.stdio;

void main(string[] args){
    auto range = File("text.txt").byLine();

    foreach( line; range ){
        if (line != ""){
            writeln(line);
            // char[] url = range.???
            // char[] num = range.???
        }
    }
}
-----
How can you read the next line while iterating over a file line by line, so that the next iteration uses the line after next? If this isn't possible byLine is a design flaw and D should instead provide a regular readLine function.

btw: What is this? A forum for a programming language that doesn't support code blocks?
February 02, 2017
There is a readln function, and this is not forum but just web frontend around mailing list. http://forum.dlang.org/help#about

Dne 2. 2. 2017 7:20 PM napsal uživatel "John Doe via Digitalmars-d-learn" < digitalmars-d-learn@puremagic.com>:

> Let's say you're trying to parse a file format like:
>
> Name
> http://example.com
> 123234
>
> Foo Bar
> http://dlang.org
> 888888
>
> with blocks separated by varying amount of blank lines.
>
> -----
> import std.stdio;
>
> void main(string[] args){
>     auto range = File("text.txt").byLine();
>
>     foreach( line; range ){
>         if (line != ""){
>             writeln(line);
>             // char[] url = range.???
>             // char[] num = range.???
>         }
>     }
> }
> -----
> How can you read the next line while iterating over a file line by line, so that the next iteration uses the line after next? If this isn't possible byLine is a design flaw and D should instead provide a regular readLine function.
>
> btw: What is this? A forum for a programming language that doesn't support code blocks?
>


February 02, 2017
Dne 2. 2. 2017 7:24 PM napsal uživatel "Daniel Kozak" <kozzi11@gmail.com>:

There is a readln function, and this is not forum but just web frontend around mailing list. http://forum.dlang.org/help#about

https://dlang.org/phobos/std_stdio.html#.File.readln


February 02, 2017
On Thursday, 2 February 2017 at 18:18:13 UTC, John Doe wrote:
> Let's say you're trying to parse a file format like:
>
> Name
> http://example.com
> 123234
>
> Foo Bar
> http://dlang.org
> 888888
>
> with blocks separated by varying amount of blank lines.
>
> -----
> import std.stdio;
>
> void main(string[] args){
>     auto range = File("text.txt").byLine();
>
>     foreach( line; range ){
>         if (line != ""){
>             writeln(line);
>             // char[] url = range.???
>             // char[] num = range.???
>         }
>     }
> }
> -----
> How can you read the next line while iterating over a file line by line, so that the next iteration uses the line after next? If this isn't possible byLine is a design flaw and D should instead provide a regular readLine function.
>
> btw: What is this? A forum for a programming language that doesn't support code blocks?

If you understand the underlying range interface, the answer becomes clear:


import std.stdio;

void main(string[] args)
{
    auto range = File("text.txt").byLineCopy();

    foreach (line; range)
    {
        if (line != "")
        {
            writeln(line);
            range.popFront;
            char[] url = range.front();
            range.popFront;
            char[] num = range.front();
        }
    }
}
February 02, 2017
Even this one could works:

import std.stdio;

void main(string[] args)
{
    auto range = File("text.txt").byLine();

    foreach (line; range)

    {
        if (line != "")
        {
            writeln(line);
            range.popFront;
            char[] url = range.front().dup;
            range.popFront;
            char[] num = range.front().dup
        }
    }
}


February 02, 2017
More range aproach, untested written on the fly from mobile phone

import std.stdio : File;
import std.range : chunks;
import.std.algorithm : map, filter, array;

void main()
{
    auto r = File("text.txt").byLine
       .filter!(a=>a.length)
       .chunks(2)
       .map!(a=>[a[0].dup, a[1].dup])
       .array;

    writeln(r);
}


February 02, 2017
On Thursday, 2 February 2017 at 18:58:46 UTC, Daniel Kozak wrote:
> Even this one could works:
>
> import std.stdio;
>
> void main(string[] args)
> {
>     auto range = File("text.txt").byLine();
>
>     foreach (line; range)
>
>     {
>         if (line != "")
>         {
>             writeln(line);
>             range.popFront;
>             char[] url = range.front().dup;
>             range.popFront;
>             char[] num = range.front().dup
>         }
>     }
> }

Thanks readln is perfect. Since I am calling readln in different places and I always need to remove the newline character I have line=line[0..$-1] all over my code. Is there are better way?

unrelated second question: Why is there no split function with a maxsplit parameter?
February 02, 2017
On 02/02/2017 11:30 AM, Daniel Kozak via Digitalmars-d-learn wrote:
>
> More range aproach, untested written on the fly from mobile phone
>
> import std.stdio : File;
> import std.range : chunks;
> import.std.algorithm : map, filter, array;
>
> void main()
> {
>     auto r = File("text.txt").byLine
>        .filter!(a=>a.length)
>        .chunks(2)
>        .map!(a=>[a[0].dup, a[1].dup])
>        .array;
>
>     writeln(r);
> }
>
>

I tried that as well but chunks() requires ForwardRange. I wrote a rough sketch of byPairs almost :) on the fly:

import std.range;
import std.stdio;
import std.algorithm;
import std.typecons;

struct ByPairs(R)
if (isInputRange!R) {
    alias E = ElementType!R;
    R range;
    Tuple!(E, E) pair;

    this (R range) {
        this.range = range;
        if (!empty) {
            prime();
        }
    }

    void prime() {
        this.pair[0] = range.front;
        range.popFront();
        this.pair[1] = range.front;
        range.popFront();
    }

    bool empty() {
        return range.empty;
    }

    auto front() {
        return pair;
    }

    void popFront() {
        assert(!empty);
        prime();
    }
}

auto byPairs(R)(R r) {
    return ByPairs!R(r);
}

void main() {
    struct Data {
        string url;
        string num;
    }

    auto result = File("deneme.txt", "r")
                  .byLineCopy
                  .filter!(line => !line.empty)
                  .byPairs;

    // Also try appending .map!(t => Data(t[0], t[1]))

    writefln("%-(%s\n%)", result);
}

Having to decide on Tuple (or requiring a factory method) is bothersome. It would be great if the programmer need not deal with the intermediate Tuple and just get their Data. So, a 'map' without needing explicit construction like

     .byPairs.make!Data

should somehow work. Or perhaps

    .mapFromTuple!Data(byPairs)

(Not tested.)

Ali

February 02, 2017
Dne 2. 2. 2017 20:35 napsal uživatel "John Doe via Digitalmars-d-learn" < digitalmars-d-learn@puremagic.com>:

On Thursday, 2 February 2017 at 18:58:46 UTC, Daniel Kozak wrote:

> Even this one could works:
>
> import std.stdio;
>
> void main(string[] args)
> {
>     auto range = File("text.txt").byLine();
>
>     foreach (line; range)
>
>     {
>         if (line != "")
>         {
>             writeln(line);
>             range.popFront;
>             char[] url = range.front().dup;
>             range.popFront;
>             char[] num = range.front().dup
>         }
>     }
> }
>

Thanks readln is perfect. Since I am calling readln in different places and I always need to remove the newline character I have line=line[0..$-1] all over my code. Is there are better way?


you can use popBack on readln od trim but it is not more elegant. Maybe open enhancement on issues.dlang.org to phobos to add parametr for not keeping line end char

unrelated second question: Why is there no split function with a maxsplit parameter?


what is maxsplit parametr, I have never use it od need it?


February 02, 2017
On Thursday, 2 February 2017 at 20:26:36 UTC, Daniel Kozak wrote:
> Dne 2. 2. 2017 20:35 napsal uživatel "John Doe via Digitalmars-d-learn" < digitalmars-d-learn@puremagic.com>:
>
> On Thursday, 2 February 2017 at 18:58:46 UTC, Daniel Kozak wrote:
>
>>[...]
>
> Thanks readln is perfect. Since I am calling readln in different places and I always need to remove the newline character I have line=line[0..$-1] all over my code. Is there are better way?
>
>
> you can use popBack on readln or trim but it is not more elegant. Maybe open enhancement on issues.dlang.org to phobos to add parameter for not keeping line end char
>
> unrelated second question: Why is there no split function with a maxsplit parameter?
>
>
> what is maxsplit parameter, I have never use it or need it?

Python's split function has an optional maxsplit parameter to specify the maximum splits that should be done. So that "1,2,3,4,5".split(',', 3) returns ['1', '2', '3', '4,5'].
« First   ‹ Prev
1 2