arrays - 如何合并字符串数组中有前导和尾随括号的元素?

标签 arrays ruby string merge

在 Ruby 中,假设我有一个字符串数组

["a", "(b", "c)", "d", "e"]

如果一个字符串的第一个字符是“(”而另一个字符串的最后一个字符是“)”,我如何合并(中间有一个空格)字符串?在上面的示例中,我希望生成的数组是

["a", "(b c)", "d", "e"]

同样,如果我的数组是

["a", "(b", "e", "c)", "d"]

我想要的结果是

["a", "(b e c)", "d"]

但是如果数组是

["(a", "c"]

["c)", "e", "(b"]

我希望数组在第一个实例中保持不变 b/c,没有带有“)”的元素,在第二个实例中,带有“)”的元素位于以“(”开头的元素之前. 我希望这是有道理的。

最佳答案

我的第一个问题是,你是怎么得到这么奇怪的数组的?它看起来像是拆分了一些不应该那样拆分的结果。

我敢肯定有更聪明的方法可以做到这一点,但一个简单的方法是遍历数组并维护一个要连接的项目缓冲区(如果没有找到结束项目,则追加到输出的末尾) :

def regroup(arr)
  out, buf = [], []

  arr.each do |elem|
    if buf.empty? && !elem.start_with?('(')
      out << elem
    else
      buf << elem

      if elem.end_with?(')')
        out << buf.join(' ')

        buf.clear
      end
    end
  end

  out.concat(buf)
end

这种方法的主要问题是它不处理嵌套组。为了支持这一点,您需要一些方法来确保在刷新缓冲区之前打开和关闭项目的数量相等:

def regroup(arr)
  out, buf, count = [], [], 0

  arr.each do |elem|
    if buf.empty? && !elem.start_with?('(')
      out << elem
    else
      buf << elem

      if elem.start_with?('(')
        count += 1
      elsif elem.end_with?(')')
        count -= 1
      end

      if count.zero?
        out << buf.join(' ')

        buf.clear
      end
    end
  end

  out.concat(buf)
end

这应该是非常有效的,因为它是对数组的一次迭代,创建的对象数量最少。不幸的是,它仍然无法处理某些情况,例如如果 ["(a", "(b)", "c)"] 应该返回 ["(a", "(b c)"]。为此,您可能需要递归函数。如果您想查看该解决方案,请告诉我。

更新:实现递归解决方案比我想象的要困难得多。我有一个工作版本,但它太丑了,我不愿意分享!如果我需要回溯,我可能会使用 Amadan 的正则表达式解决方案或类似的解决方案。我还编写了一个带有原始回溯的解决方案版本:

def regroup(arr)
  out, pos = [], 0

  loop do
    should_retry = regroup_worker(arr.drop(pos)) do |elem, size=1|
      out << elem

      pos += size
    end

    break out unless should_retry
  end
end

def regroup_worker(arr)
  buf, count = [], 0

  arr.each do |elem|
    if buf.empty? && !elem.start_with?('(')
      yield elem
    else
      buf << elem

      if elem.start_with?('(')
        count += 1
      elsif elem.end_with?(')')
        count -= 1
      end

      if count.zero?
        yield buf.join(' '), buf.size

        buf.clear
      end
    end
  end

  # we have unbalanced parens, so let the caller consume the "bad" opening
  # paren and try again (returns false if nothing left to do)
  yield buf.first unless buf.empty?
end

regroup(["(a", "(b", "c)"]) # => ["(a", "(b c)"]

希望对您有所帮助!这当然是一个值得思考和尝试解决的有趣问题。

关于arrays - 如何合并字符串数组中有前导和尾随括号的元素?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/47254500/

相关文章:

javascript - 如何在 PHP foreach 中使用 ajax?

c - 结构数组崩溃程序 C

ruby-on-rails - 我的 Rails 4.2.6 应用程序使用两个数据库。我可以只使用一个进行测试吗?

java - 如何在字符串中查找重复项?

string - 如何遍历 Postgresql 中字符串的字符?

php - 如何清空属于关联数组的键的内容而不取消 PHP 中的键设置?

python - python 列表的新手

ruby-on-rails - Rails 在 html 文件中渲染带有空格的字符串

php - Ruby 与 PHP 中 'or' 条件的处理

c++ - 在已编译的 exe 中编辑字符串变量? C++ win32