Thread overview | ||||||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
|
June 22, 2020 how to skip the next (n) item & continue from (n+1) with a range ? e.g. in File(fn).byLine(); | ||||
---|---|---|---|---|
| ||||
Hi, I need this logic: ``` auto range = File(fn).byLine(); foreach (line; range) { if (comeCond(line)) { // skip the next n line // and continue the foreach loop from the (n+1) line } else { regularProcess(line); } } ``` Is it possible to do this in a foreach loop? If not, how can I achieve that, esp. when reading a file line-by-line? do I have to read the whole file into memory, and split by line and using regular `for` loop? |
June 22, 2020 Re: how to skip the next (n) item & continue from (n+1) with a range ? e.g. in File(fn).byLine(); | ||||
---|---|---|---|---|
| ||||
Posted in reply to mw | On 6/22/20 3:53 PM, mw wrote:
> Hi,
>
> I need this logic:
>
> ```
> auto range = File(fn).byLine();
> foreach (line; range) {
> if (comeCond(line)) {
> // skip the next n line
> // and continue the foreach loop from the (n+1) line
> } else {
> regularProcess(line);
> }
> }
> ```
>
> Is it possible to do this in a foreach loop?
I wouldn't recommend it, instead do a while loop:
auto range = File(fn).byLine;
while(!range.empty)
{
auto line = range.front;
if(someCond(line)) {
range.popFrontN(n);
} else {
regularProcess(line);
range.popFront;
}
}
-Steve
|
June 22, 2020 Re: how to skip the next (n) item & continue from (n+1) with a range ? e.g. in File(fn).byLine(); | ||||
---|---|---|---|---|
| ||||
Posted in reply to mw | If you are referring to the next line, not the next n lines, that's a simple `continue;` statement. |
June 22, 2020 Re: how to skip the next (n) item & continue from (n+1) with a range ? e.g. in File(fn).byLine(); | ||||
---|---|---|---|---|
| ||||
Posted in reply to kinke | On Monday, 22 June 2020 at 20:02:22 UTC, kinke wrote:
> If you are referring to the next line, not the next n lines, that's a simple `continue;` statement.
[Please discard, that'd obviously be skipping the *current* line.]
|
June 22, 2020 Re: how to skip the next (n) item & continue from (n+1) with a range ? e.g. in File(fn).byLine(); | ||||
---|---|---|---|---|
| ||||
Posted in reply to Steven Schveighoffer | On Monday, 22 June 2020 at 20:00:50 UTC, Steven Schveighoffer wrote:
> I wouldn't recommend it, instead do a while loop:
>
> auto range = File(fn).byLine;
>
> while(!range.empty)
> {
> auto line = range.front;
> if(someCond(line)) {
> range.popFrontN(n);
> } else {
> regularProcess(line);
> range.popFront;
> }
> }
Thanks.
so `front` is peek, and `popFront` is the pop action whose return type is `void`, why we need two *separate* calls instead of just let `popFront` return T (or do we have another function for this)? i.e if the user forget `popFront`, it will prone to infinite loop bug?
|
June 22, 2020 Re: how to skip the next (n) item & continue from (n+1) with a range ? e.g. in File(fn).byLine(); | ||||
---|---|---|---|---|
| ||||
Posted in reply to mw | On Monday, 22 June 2020 at 20:46:30 UTC, mw wrote: > On Monday, 22 June 2020 at 20:00:50 UTC, Steven Schveighoffer wrote: >> I wouldn't recommend it, instead do a while loop: >> >> auto range = File(fn).byLine; >> >> while(!range.empty) >> { >> auto line = range.front; >> if(someCond(line)) { >> range.popFrontN(n); I'm asking this, because here it need to be range.popFrontN(n+1); i.e. bug-prone can be fixed by: auto line = range.front; range.popFront; // pop immediately >> } else { >> regularProcess(line); >> range.popFront; >> } >> } > > Thanks. > > so `front` is peek, and `popFront` is the pop action whose return type is `void`, why we need two *separate* calls instead of just let `popFront` return T (or do we have another function for this)? i.e if the user forget `popFront`, it will prone to infinite loop bug? so my question. |
June 22, 2020 Re: how to skip the next (n) item & continue from (n+1) with a range ? e.g. in File(fn).byLine(); | ||||
---|---|---|---|---|
| ||||
Posted in reply to mw | On Monday, 22 June 2020 at 20:49:55 UTC, mw wrote: > On Monday, 22 June 2020 at 20:46:30 UTC, mw wrote: >> On Monday, 22 June 2020 at 20:00:50 UTC, Steven Schveighoffer wrote: >>> I wouldn't recommend it, instead do a while loop: >>> >>> auto range = File(fn).byLine; >>> >>> while(!range.empty) >>> { >>> auto line = range.front; >>> if(someCond(line)) { >>> range.popFrontN(n); > > I'm asking this, because here it need to be either > range.popFrontN(n+1); > > i.e. bug-prone or > can be fixed by: > auto line = range.front; > range.popFront; // pop immediately of course. |
June 22, 2020 Re: how to skip the next (n) item & continue from (n+1) with a range ? e.g. in File(fn).byLine(); | ||||
---|---|---|---|---|
| ||||
Posted in reply to mw | On 6/22/20 1:46 PM, mw wrote: > so `front` is peek, and `popFront` is the pop action whose return type > is `void`, why we need two *separate* calls instead of just let > `popFront` return T Others have other explanations for this but my understanding is about exception safety: If it changed internal state and returned the front object, you would no be able to make a function like popFront() strongly exception safe. (There are ample documentation for this topic in C++ circles.) Another reason is cohesion: We want functions to have as little responsibility as possible (ideally single). > (or do we have another function for this)? There are many useful functions in std.range: https://dlang.org/phobos/std_range.html The "take" and "drop" functions may be useful. Ali |
June 22, 2020 Re: how to skip the next (n) item & continue from (n+1) with a range ? e.g. in File(fn).byLine(); | ||||
---|---|---|---|---|
| ||||
Posted in reply to mw | On Mon, Jun 22, 2020 at 08:51:49PM +0000, mw via Digitalmars-d-learn wrote: [...] > > auto line = range.front; > > range.popFront; // pop immediately [...] This is dangerous, because it assumes .front is not invalidated by .popFront. It will not work, for example, with byLine because .front returns a buffer which is reused by .popFront (a so-called "transient range"). In the realm of defensive programming, it is better to make less assumptions (don't assume .front remains valid after .popFront) than add implicit assumptions (range is non-transient) that may break in subtle ways that are not immediately obvious. T -- Why ask rhetorical questions? -- JC |
June 22, 2020 Re: how to skip the next (n) item & continue from (n+1) with a range ? e.g. in File(fn).byLine(); | ||||
---|---|---|---|---|
| ||||
Posted in reply to mw | On 6/22/20 4:49 PM, mw wrote: > On Monday, 22 June 2020 at 20:46:30 UTC, mw wrote: >> On Monday, 22 June 2020 at 20:00:50 UTC, Steven Schveighoffer wrote: >>> I wouldn't recommend it, instead do a while loop: >>> >>> auto range = File(fn).byLine; >>> >>> while(!range.empty) >>> { >>> auto line = range.front; >>> if(someCond(line)) { >>> range.popFrontN(n); > > I'm asking this, because here it need to be range.popFrontN(n+1); `n` actually isn't defined, you defined it in a comment in your original code ;) I just threw it in there. Of course, make sure it works how you are expecting, I don't know what your code is doing. > > i.e. bug-prone > > can be fixed by: > auto line = range.front; > range.popFront; // pop immediately This is a bad idea, once you popFront, the original front is possibly invalid (and technically is the case for byLine). > > >>> } else { >>> regularProcess(line); >>> range.popFront; >>> } >>> } >> >> Thanks. >> >> so `front` is peek, and `popFront` is the pop action whose return type is `void`, why we need two *separate* calls instead of just let `popFront` return T (or do we have another function for this)? i.e if the user forget `popFront`, it will prone to infinite loop bug? > > so my question. There is no requirement to actually construct members. e.g. popFrontN calls popFront N times, but does not actually invoke front at all. Separating the concerns is for correctness and performance. -Steve |
Copyright © 1999-2021 by the D Language Foundation