【问题标题】:How to get all combinations of available keys in a string如何获取字符串中可用键的所有组合
【发布时间】:2016-01-26 00:23:59
【问题描述】:

我有一个这样的字符串:

'show -drum-, -drum- and -drum-'

每个/-[a-z]+-/ 键的选项数组:

{
  '-drum-' => %w{kick snare hihat crash},
  ...
}

我想进行所有可能的替换,包括:

[
  'show kick, snare and hihat',
  'show kick, hihat and snare',
  'show snare, hihat and kick',
  'show snare, kick and hihat',
  'show hihat, snare and kick',
  'show hihat, kick and snare',
  'show crash, kick and snare',
  'show crash, snare and kick',
  'show hihat, snare and crash',
  ...
]

理想情况下,这会发生而无需任何重复,尽管我会接受会返回的解决方案,例如“show kick, kick and kick”等。

哈希中还有其他键替换,所以我也必须对它们进行独特的组合。

【问题讨论】:

  • 欢迎来到 Stack Overflow。 “......我会接受解决方案......” - 我们希望看到您为解决问题所做的努力。你试过什么?为什么它不起作用?如果您还没有尝试过,假设我们会编写解决方案是不好的,因此请向我们展示您的工作以供我们纠正,而不是从头开始编写一些东西。阅读“How to Ask”和“minimal reproducible example”。

标签: ruby string substitution


【解决方案1】:

有趣的挑战。

def each_replacement(pattern, repl_keys)
  return enum_for(__method__, pattern, repl_keys) unless block_given?

  pattern.gsub!('%', '%%')
  keys = repl_keys.keys
  key_counts = Hash[keys.map { |key| [key, pattern.scan(key).count] }]
  key_permutations = repl_keys.lazy.map { |key, repl|
    combinations = repl.combination(key_counts[key])
    combinations.flat_map { |comb|
      comb.permutation.to_a
    }
  }.inject(&:product)
  key_permutations.each do |perm|
    text = pattern
    keys.zip(perm).each do |key, repl|
      text = text.gsub(key, '%s') % repl
    end
    yield text
  end
end

pattern = '-action- -drum-, -drum- and -drum-'
keys = {
  '-drum-' => %w{kick snare hihat crash},
  '-action-' => %w{hit smash}
}
puts each_replacement(pattern, keys).to_a

【讨论】:

  • 太好了,谢谢!正是我需要的。我可以在这里学习一些新方法:)
【解决方案2】:
a = ['kick','snare', 'hihat']
a.permutation.each do |p|
  puts "play %s, %s and %s" % p
end

有一个内置的permutation 函数。在上面的示例中,将所有内容存储在一个数组中,然后调用permutation。之后使用p 并插入目标字符串中的值。

输出是:

play kick, snare and hihat
play kick, hihat and snare
play snare, kick and hihat
play snare, hihat and kick
play hihat, kick and snare
play hihat, snare and kick

这是广义形式:

rep = {
  '-drum-' => %w{kick snare hihat crash},
  '-zoo-' => %w{zebra lion dog},
  '-one-' => %w{one},
  '-ping-' => %w{pong noreply}
}

template = 'show -drum- on -zoo-, -one- -ping- for -drum-, -ping- for -drum- or -drum- -zoo- -zoo-'
accumulator = []
accumulator << template

rep.keys.each do |key|
  new_accumulator = []
  accumulator.each do |acc|
    transformed_template = acc.gsub(key, '%s')
    rep[key].permutation.each do |p|
     new_accumulator << transformed_template % p
    end
  end
  accumulator = new_accumulator
end

accumulator.each do |fin|
  puts fin
end

【讨论】:

  • 我可能不太清楚,不会总是有三个键和三个放置它们的位置。鼓阵列中实际上有七个项目。
  • 它的工作原理与七个键和七个放置它们的位置相同。
  • 七把钥匙和三个地方怎么样?还是七加一?
  • 是的。你可以做的不止 1 个。你只是在推断这个解决方案
  • 谢谢!这实际上可能是比@Amadan 建议的稍微整洁的解决方案。我必须做一些基准测试才能做出决定。
【解决方案3】:

使用单个目标替换对:

target = /-drum-/
replacement = %w{kick snare hihat}
a = ["show -drum-, -drum- and -drum-"]
while a.first =~ target
  a = a.flat_map{|s| replacement.map{|r| s.sub(target, r)}}
end
a # => ["show kick, kick and kick", "show kick, kick and snare", "show kick, kick and hihat", "show kick, snare and kick", "show kick, snare and snare", "show kick, snare and hihat", "show kick, hihat and kick", "show kick, hihat and snare", "show kick, hihat and hihat", "show snare, kick and kick", "show snare, kick and snare", "show snare, kick and hihat", "show snare, snare and kick", "show snare, snare and snare", "show snare, snare and hihat", "show snare, hihat and kick", "show snare, hihat and snare", "show snare, hihat and hihat", "show hihat, kick and kick", "show hihat, kick and snare", "show hihat, kick and hihat", "show hihat, snare and kick", "show hihat, snare and snare", "show hihat, snare and hihat", "show hihat, hihat and kick", "show hihat, hihat and snare", "show hihat, hihat and hihat"]
a.length # => 27

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2012-08-16
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-03-20
    相关资源
    最近更新 更多