Ruby 复杂字符串数组到 float 数组

Ruby complex strings array to array of float

提问人:Seto 提问时间:10/12/2023 最后编辑:Seto 更新时间:10/14/2023 访问量:138

问:

我正在尝试将这个(相当复杂的)浮点字符串数组转换为浮点数组,但没有运气:

[  5.85142857   6.10684807   6.15328798   6.31582766   6.96598639
   7.61614512   7.87156463   8.73070295   9.38086168   9.65950113
  10.51863946  12.07437642  12.32979592  13.39791383  13.63011338
  13.86231293  14.09451247  14.72145125  14.97687075  15.85922902 ]

我试过什么:

  def onset_string_to_array(onset)
    # Remove the brackets.
    onset = onset.tr('[]', '')
    # Strip whitespace.
    onset = onset.strip
    # Split by newline character.
    onset_lines = onset.split("\n")
    # loop through each line.
    onset_array = []
    onset_array.push *onset_lines.map do |line|
      # Split by space character.
      line_array = line.split
      # Return one float per line.
      line_array.map(&:to_f)
    end
    onset_array
  end

给我这个:

[
  "0.53405896   0.7662585    0.99845805   1.20743764   1.41641723",
  "   1.64861678   1.85759637   2.32199546   3.43655329   3.57587302",
  "   4.08671202   4.7600907    4.99229025   5.87464853   6.52480726",
  "   6.78022676   7.66258503   8.33596372   9.4737415   10.12390023",
  "  10.35609977  10.750839    11.2152381   11.88861678  12.14403628",
  "  12.60843537  12.84063492  13.04961451  13.69977324  13.95519274",
  "  14.11773243  14.58213152  14.79111111  15.4644898   15.69668934",
  "  16.60226757  17.27564626  17.5078458   18.39020408  19.06358277",
  ## More lines...
  " 126.54875283 127.45433107 129.03328798 129.21904762 130.77478458",
  " 131.00698413 131.86612245 132.81814059 133.35219955 134.55963719",
  " 135.14013605"
]

我想要得到什么:

[ 0.53405896, 0.7662585, 0.99845805, 1.20743764, 1.41641723, 1.64861678, ...]

有什么线索吗?

数组 Ruby 展平

评论

3赞 Mark Reed 10/12/2023
对不起,什么?你有那个文本,你正在尝试将其解析为数组?扁平化与它有什么关系?一开始看起来很平淡;如果有的话,看起来你正在尝试让它更深入地嵌套在你的代码中......告诉我们:你希望结果是什么样子,你得到的是什么,而且要准确!
1赞 Cary Swoveland 10/12/2023
这不是一个有效的 Ruby 对象。在适当的情况下显示引号。举例时,请始终显示所需的结果。首先,不清楚你是否想以 (string) 或 (float) 结束。"10.51863946"10.51863946
0赞 Jörg W Mittag 10/12/2023
“没有运气”并不是一个足够精确的问题描述,我们无法为您提供帮助。什么不起作用?它怎么不工作?你的代码有什么问题?您是否收到错误消息?错误消息是什么?你得到的结果不是你期望的结果吗?你期望什么结果,为什么,你得到的结果是什么,两者有什么不同?您观察到的行为是否不是期望的行为?什么是期望的行为,为什么,观察到的行为是什么,它们在哪些方面有所不同?
0赞 Jörg W Mittag 10/12/2023
idownvotedbecau.se/itsnotworking idownvotedbecau.se/noexceptiondetails
0赞 Seto 10/14/2023
我弄错了扁平化的含义。只想在那里保存一个浮点数数组。

答:

0赞 user229044 10/12/2023 #1

你已经点亮并剥离了前导/拖曳的空格,但在那之后,你就走上了一条不必要的复杂道路。[]

只需调用 ,默认情况下,它将贪婪地匹配空格作为其分隔符:split

str = '[  5.85142857   6.10684807   6.15328798   6.31582766   6.96598639
   7.61614512   7.87156463   8.73070295   9.38086168   9.65950113
  10.51863946  12.07437642  12.32979592  13.39791383  13.63011338
  13.86231293  14.09451247  14.72145125  14.97687075  15.85922902 ]'

str.tr('[]', '').strip.split.map(&:to_f)

至于为什么你的代码会失败,你正在将一个数组数组分散到你的初始数组上,这意味着你从来没有真正展平它。

如果由于某种原因,您必须避免通过正则表达式拆分整个字符串,而是逐行拆分,则应跳过 而只使用 :array.push(*other_array.map)flat_map

str = '5.85142857   6.10684807   6.15328798   6.31582766   6.96598639
   7.61614512   7.87156463   8.73070295   9.38086168   9.65950113
  10.51863946  12.07437642  12.32979592  13.39791383  13.63011338
  13.86231293  14.09451247  14.72145125  14.97687075  15.85922902'

str.lines.flat_map { |line| line.split.map(&:to_f) }

任一选项都会生成您想要的浮动平面列表:

[5.85142857,
 6.10684807,
 6.15328798,
 6.31582766,
 6.96598639,
 7.61614512,
 7.87156463,
 8.73070295,
 9.38086168,
 9.65950113,
 10.51863946,
 12.07437642,
 12.32979592,
 13.39791383,
 13.63011338,
 13.86231293,
 14.09451247,
 14.72145125,
 14.97687075,
 15.85922902]

评论

1赞 engineersmnky 10/12/2023
str.scan(/\d+\.\d+/).map(&:to_f)
2赞 user229044 10/12/2023
@engineersmnky 无论哪种方式。在空格上拆分需要不太复杂的正则表达式并考虑 ,并且不必生成逐渐复杂的正则表达式。1.1-1.01e6
2赞 ShadowRanger 10/12/2023
你在这里根本不需要正则表达式。 可能会变成(假设没有人在乱搞),或者如果你想防止乱搞,。Ruby 在这里与 Python 不同;如果你做了一个无限制,并且要拆分的分隔符是 ,它会在空格运行时拆分(其中 Python 区分 和 ,只有前者得到特殊的空格运行处理)。.split(/\s+/).split$;$;.split(' ')split' '.split().split(' ')
0赞 user229044 10/12/2023
@ShadowRanger 当然,你是对的。应该尝试一下,但几乎任何其他语言都是非常不明显的行为。
0赞 ShadowRanger 10/12/2023
@user229044:是的,我今天早些时候碰到的和一样,而且是......相当令人惊讶。没有参数的行为是“在空格上运行时拆分”,并不是那么不直观(即使它与显式分隔符的行为不一致,就像在 Python 中一样),但行为方式相同,在不是空格字符的东西上拆分?非常奇怪的选择。.split.split(' ').split(' ')
4赞 mechnicov 10/12/2023 #2

要解析此字符串,您可以:

onset.delete('[]').split.map(&:to_f)

(1)首先删除括号,(2)然后用空格将字符串拆分为子字符串,(3)最后转换为浮点数

onset =
  '[  5.85142857   6.10684807   6.15328798   6.31582766   6.96598639
      7.61614512   7.87156463   8.73070295   9.38086168   9.65950113
     10.51863946  12.07437642  12.32979592  13.39791383  13.63011338
     13.86231293  14.09451247  14.72145125  14.97687075  15.85922902 ]'

onset.delete('[]').split.map(&:to_f)
# => 
# [5.85142857,
#  6.10684807,
#  6.15328798,
#  6.31582766,
#  6.96598639,
#  7.61614512,
#  7.87156463,
#  8.73070295,
#  9.38086168,
#  9.65950113,
#  10.51863946,
#  12.07437642,
#  12.32979592,
#  13.39791383,
#  13.63011338,
#  13.86231293,
#  14.09451247,
#  14.72145125,
#  14.97687075,
#  15.85922902]

顺便说一句,Ruby 有内置的方法从字符串中获取行,你不需要用换行符拆分它,只需使用string.lines

评论

0赞 ShadowRanger 10/12/2023
需要明确的是,没有参数(和默认值)会在任何类型的空格的序列(“运行”)上拆分,而不仅仅是空格字符。这就是你在这里想要的,将换行符和空格字符及其混合物视为一个要拆分的东西,而不是在组件之间获得空字符串,或者只在空格或换行符上拆分。.split$;
0赞 Cary Swoveland 10/12/2023
onset[1..-2]是 的替代方法。onset.delete('[]')...
0赞 mechnicov 10/12/2023
@CarySwoveland我最初想过,但我们不知道这个结构是什么样子的,谁知道最后可能是']'。所以出于某种原因,我下定决心,决定而不是初步的喜欢deletestriponset.strip[1..-2].split.map(&:to_f)
1赞 Cary Swoveland 10/12/2023
“所以出于某种原因,我下定了决心......”是我经常做的事情,通常是非理性的......
1赞 Cary Swoveland 10/12/2023 #3

我假设

str = "[  5.85142857   6.10684807   6.15328798   6.31582766   6.96598639\n  7.61614512   7.87156463   8.73070295   9.38086168   9.65950113\n  10.51863946  12.07437642  12.32979592  13.39791383  13.63011338\n  13.86231293  14.09451247  14.72145125  14.97687075  15.85922902 ]".

在这种情况下,你可以写

str.lines.map { |line| line.scan(/\d+\.\d+/).map(&:to_f) }
  #=> [[ 5.85142857,  6.10684807,  6.15328798,  6.31582766,  6.96598639],
  #    [ 7.61614512,  7.87156463,  8.73070295,  9.38086168,  9.65950113],
  #    [10.51863946, 12.07437642, 12.32979592, 13.39791383, 13.63011338],
  #    [13.86231293, 14.09451247, 14.72145125, 14.97687075, 15.85922902]]

例如,当

line = "10.51863946, 12.07437642, 12.32979592, 13.39791383, 13.63011338"

然后

arr = line.scan(/\d+\.\d+/)
  #=> ["10.51863946", "12.07437642", "12.32979592", "13.39791383", "13.63011338"]
arr.map(&:to_f)
  #=> [10.51863946, 12.07437642, 12.32979592, 13.39791383, 13.63011338]

如果“扁平化”是指你希望生成一个包含 20 个浮点数的数组,而不是由四个数组组成的数组,每个数组包含五个浮点数(如上所述),则可以将

str.scan(/\d+\.\d+/).map(&:to_f)
  #=> [ 5.85142857,  6.10684807,  6.15328798,  6.31582766,  6.96598639,
  #     7.61614512,  7.87156463,  8.73070295,  9.38086168,  9.65950113,
  #    10.51863946, 12.07437642, 12.32979592, 13.39791383, 13.63011338,
  #    13.86231293, 14.09451247, 14.72145125, 14.97687075, 15.85922902]

评论

0赞 Chris 10/12/2023
如果并非所有数字都有小数位,则可能需要将正则表达式的部分设为可选。\.\d+
0赞 Cary Swoveland 10/12/2023
谢谢,@Chris,可以做到,但是,给定这个例子,与浮点数混合在一起的整数(即它的字符串表示)可能是坏数据,所以以我所拥有的,我不会标记它,并且按照你的建议进行更改会把坏的看作是好的。双输双赢。在真正的应用程序中可以完成更多工作。