【问题标题】:How to efficiently split a very long (multiple million characters) string after every nth character in Ruby?如何在Ruby中的每个第n个字符之后有效地分割一个很长(数百万个字符)的字符串?
【发布时间】:2019-09-12 23:00:41
【问题描述】:

假设我有一个字符串

string = "hellohellohey"

我想每隔第二个字符拆分一次,这样看起来像这样

string = ["he","ll","oh","el","lo","he","y"]

我尝试使用scan(/.{2}/)方法,但如果数组项不能被2除,它就不起作用。

编辑: 有必要告诉你,2 字符的东西是一个例子。我正在做一些大事,所以我将每 8 百万 个字符拆分一次。因此,将其拆分为单个字符并使用 each_slice 在这里不起作用。它只会冻结我的笔记本电脑。

【问题讨论】:

  • 尝试使用 .{1,2} 匹配 1 或 2 次。

标签: arrays ruby string split


【解决方案1】:

处理(非常)大的字符串时,将它们包装在StringIO 中会很有用。它提供了对字符串的高效文件式访问。

例如,您可以通过 StringIO#each 读取每个 n 个字符:

string = "hellohellohey"
string_io = StringIO.new(string)

string_io.each(5) do |substring|
  p substring
end

输出:

"hello"
"hello"
"hey"

【讨论】:

  • 谢谢,它有效。但是,当我尝试计算数组中的项目数时,它告诉我它是一个枚举器。编辑:没关系,我用.to_a
  • @tequila 这是预期的。对于一个块,StringIO#each 产生字符/子字符串。没有块,它返回一个枚举器。我假设您想跳过数组创建并处理子字符串。
【解决方案2】:

点匹配除换行符以外的任何字符。您正在尝试匹配任何字符的 2 次,如果字符串长度为奇数,则不会匹配最后一个字符。

您可以使用 quantifier {1,2} 贪心,因此它首先尝试匹配 2 次。

.{1,2}

a demo

如果您只想匹配小写字符 a-z,您也可以使用 [a-z] 而不是点。

【讨论】:

  • 也有效:/..?/ 这只是一个字符。不过,您在此处拥有的 {} 版本更加灵活,您可以使用 2,59,300 或任何您需要的东西。
  • 此外,您可能希望添加m 修饰符以使. 匹配任何字符(默认情况下不匹配换行符)。
【解决方案3】:

您可以链接多个方法,如下所示:

string = 'hellohellohey'
string.chars.each_slice(2).map { |s| s.join }
# => ["he", "ll", "oh", "el", "lo", "he", "y"]

#chars 将字符串转换为字符数组。

#each_slice 将数组拆分为所需数量的部分。

更新 - 没有中间/临时数组

根据 cmets,感谢@Cary Swoveland,可以避免临时数组,如下所示。

string.each_char.each_slice(2).map { |s| s.join }

#each_char 给出每个字符的枚举器。

【讨论】:

  • 一个小点,小到几乎看不出来:我建议你在Enumerable方法后使用each_char而不是chars,以避免创建临时数组@ 987654329@.
  • 我明白你的意思@CarySwoveland,我从同样的事情开始,但后来我无法在each_char 之后收集 2 个/所需的字符数。你能想到以某种方式链接它吗?
  • string.each_char.each_slice(2).map { |s| s.join }。注意string.each_char.each_slice(2) #=> #<Enumerator: #<Enumerator: "hellohellohey":each_char>:each_slice(2)> 的返回值,一种复合枚举器
  • 一次将字符串分割为 10000 个字符有帮助吗? string[0..10000]
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2022-01-18
  • 2011-05-07
  • 1970-01-01
  • 2022-01-15
相关资源
最近更新 更多