9

给定一个字符串string,计算其中行数的最快/最有效方法是什么?将接受任何 Rebol 风格的最佳答案。我一直在假设该parse [some [thru]]组合是遍历字符串的最快方式,但后来我不确定,因此转向 SO:

count-lines: func [string [string!] /local count][
    parse/all string [
        (count: 1) some [thru newline (count: count + 1)]
    ]
    count
]

或者:

count-lines: func [string [string!] /local count][
    count: 0
    until [
        count: count + 1
        not string: find/tail string newline
    ]
    count
]

那么柜台呢?重复效率如何?

count-lines: func [string [string!]][
    repeat count length? string [
        unless string: find/tail string newline [
            break/return count
        ]
    ]
]

更新:行数遵循文本编辑器原则:

空的 TextMate 文档

空文档的行数仍然为 1。所以:

>> count-lines ""
== 1
>> count-lines "^/"
== 2
4

9 回答 9

4

正如 BrianH 所建议的,增强的 PARSE 版本:

i: 1 ; add one as TextMate
parse text [any [thru newline (++ i)]]
print i
于 2013-02-19T22:44:26.557 回答
4
count-lines: func [
    str
    /local sort-str ][
sort-str: sort join str "^/"
1 + subtract index? find/last sort-str "^/" index? find sort-str "^/"
]
于 2013-02-13T12:12:03.473 回答
3

parse这是我能想到的最简单的非版本:

count-lines: function [text [string!]] [
    i: 1
    find-all text newline [++ i]
    i
]

它使用function++来自 Rebol 的更新版本,以及find-all来自 R3 或 R2/Forward。您可以查看find-all并内联您找到和优化的内容,但这样的情况正是我们所写find-all的,所以为什么不使用它呢?

于 2013-02-20T18:37:08.673 回答
2

为什么没有人提供我想知道的最简单的解决方案:)

t: "abc^/de^/f^/ghi"
i: 0 until [i: i + 1 not t: find/tail t newline] i
== 4

不确定性能,但我认为它很快,因为 UNTIL 和 FIND 是本地人。WHILE 也可以使用。

i: 1 while [t: find/tail t newline] [i: i + 1] i
== 4

只需要检查空字符串。如果它是一个函数,则需要对参数系列进行 HEADed。

于 2013-02-21T12:15:54.200 回答
2

remove-each 可以很快,因为它是原生的

s: "1^/2^/3"
a: length? s
print a - length? remove-each v s [v = #"^/"]
; >> 2

或作为一个函数

>> f: func [s] [print [(length? s) - (length? remove-each v s [v = #"^/"])]]
>> f "1^/2^/3"
== 2
于 2013-02-18T08:57:19.673 回答
2

这对我来说是最好的:

temp: read/lines %mytext.txt
length? temp
于 2013-02-08T08:49:10.017 回答
2

不是最有效的,但可能是最快的解决方案之一(无论如何,如果运行基准测试,我想看看这个解决方案是如何执行的):

>> s: "1^/2^/ ^/^/3"
>> (length? s) - length? trim/with copy s newline
== 4
于 2013-09-26T15:04:45.183 回答
1

不知道性能和最后一行规则(r3)。

>> length? parse "1^/2^/3" "^/"
== 3
于 2013-02-11T01:39:38.990 回答
0

hehehe 读/行长度?temp 是我认为关于 read/lines -> foreach 行 temps [ count: count + 1] 的一件好事

另一种方法是做

temp: "line 1 ^M line2 ^M  line3 ^M "
length? parse temp newline ; that cuts the strings into a block 
;of multiple strings that represent each a line [ "line 1" "line2" "line3" ] 
:then you count how much  strings you have in the block with length? 

我喜欢用 rebol 编码,这太有趣了

编辑我没有阅读整篇文章,所以我的解决方案已经以不同的方式提出......

可以修改我发布已发布解决方案的罪过,我将对该解决方案的意外行为提出洞察评论。不计算多个链式回车(使用 rebol3 linux ...)

>> a: "line1 ^M line2 ^M line3 ^M^M"
== "line1 ^M line2 ^M line3 ^M^M"

>> length? parse a newline 
== 3
于 2013-05-16T18:28:57.127 回答