【问题标题】:How to find index of a substring?如何找到子字符串的索引?
【发布时间】:2017-05-10 02:37:36
【问题描述】:

寻找相当于 Ruby 的 Elixir:

"john.snow@domain.com".index("@")         # => 9
"john.snow@domain.com".index("domain")    # => 10

【问题讨论】:

    标签: elixir


    【解决方案1】:

    我认为没有任何 Elixir 包装器,请参阅 #1119

    在此之前您可以直接拨打:binary.match

    iex(1)> :binary.match "john.snow@domain.com", "@"
    {9, 1}
    iex(2)> :binary.match "john.snow@domain.com", "domain"
    {10, 6}
    

    返回值是一个包含索引和匹配长度的元组。您可以通过管道将索引提取到|> elem(0) 或使用模式匹配。

    请注意,如果在字符串中找不到子字符串,:binary.match 将返回 :nomatch

    【讨论】:

      【解决方案2】:

      TL;DR:String.index/2 故意丢失,因为存在更智能的替代方案String.split/2 通常会解决根本问题 - 并且性能更好。

      • 我假设我们在这里讨论的是 UTF-8 字符串,并期望干净地处理非 ASCII 字符。

      • Elixir 鼓励快速编写代码。事实证明,我们通常尝试使用 String.index/2 解决的问题可以以更智能的方式解决,在不降低代码可读性的情况下极大地提高性能。

      • 更智能的解决方案是使用 String.split/2 和/或其他类似的 String 模块函数。 String.split/2 在字节级别上工作,同时仍能正确处理字素。它不会出错,因为两个参数都是字符串! String.index/2 必须在字素级别上工作,在整个字符串中缓慢搜索。

      • 因此,String.index/2 不太可能被添加到语言中,除非出现了现有函数无法彻底解决的非常引人注目的用例。

      • 另请参阅有关此问题的 elixir-lang-core 讨论: https://groups.google.com/forum/#!topic/elixir-lang-core/S0yrDxlJCss

      • 另一方面,Elixir 在其成熟的 Unicode 支持方面非常独特。虽然大多数语言都在代码点级别(俗称“字符”)上工作,但 Elixir 使用更高级别的字素概念。字素是用户认为的一个字符(可以说它是对“字符”的更实际的理解)。字形可以包含多个代码点(而代码点又可以包含多个字节)。

      最后,如果我们真的需要索引:

      case String.split("john.snow@domain.com", "domain", parts: 2) do
        [left, _] -> String.length(left)
        [_] -> nil
      end
      

      【讨论】:

      • String.split/2 是否已被弃用?我只在最近的文档中看到 split/1 和 split/3。
      【解决方案3】:

      您可以使用Regex.run/3 并将其作为选项传递return: :index

      iex(5)> [{start, len}] = Regex.run(~r/abc/, " abc ", return: :index)
      [{1, 3}]
      

      【讨论】:

      • 请注意,如果您需要查找匹配项的所有索引,可以使用Regex.scan/3
      【解决方案4】:

      您可以使用:binary.match/3获取字节索引

      {index, length} = :binary.match("aéiou", "o")    
      {4, 1}
      

      如果您想要字符串中的位置,请使用:

      "aéiou" |> to_char_list() |> Enum.find_index(&(&1 == ?o))
      3
      

      String 模块文档解释了字节长度和字符串长度之间的区别。

      【讨论】:

      • 警告! :binary.match 需要一个“模式”作为它的第二个参数,功能很像正则表达式。但是,如果真正的目的是获取重复字符串的实数,那么您应该使用“String.split”,如果正确实施,其功能与 python 的 str.find 和 javascript 的 str.indexOf 相同。其次,应该尽可能避免使用 Enum.find_index ,因为 elixir 有它的递归模式并且以这种方式进行了优化。如果您不想想太多,这是一种快速的方法。
      【解决方案5】:
      # index (as INSTR from basic...)
      
      ...
       import IO, except: [inspect: 1]  
       puts index "algopara ver", "ver" 
      
       def index( mainstring, searchstring) do 
         tuple = (:binary.match mainstring, searchstring)
         if tuple === :nomatch do 
            0 
         else 
            elem(tuple,0) 
         end  
       end 
      ... 
      
      9
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2021-12-19
        • 1970-01-01
        • 2011-03-14
        • 2020-06-08
        • 2012-05-26
        • 1970-01-01
        • 2014-03-17
        相关资源
        最近更新 更多