Genera un intervallo diverso in Ruby, ovvero tutto il possibile / [0-9A-Za-z] {3} /

StackOverflow https://stackoverflow.com/questions/613697

  •  03-07-2019
  •  | 
  •  

Domanda

Sento che sto usando Ruby nel modo sbagliato qui: voglio generare tutte le possibili corrispondenze per l'espressione regolare / [0-9A-Za-z] {3} /

Non riesco a usare succ perché " 999 " .succ = > " 1000 " e " zZz " .succ = > & Quot; AAAA " . Sto riscontrando problemi nell'uso degli intervalli perché non riesco a unire (0..9), ('A' .. 'Z'), ('a' .. 'z')

Quindi ho scritto:

def alphaNumeric
  #range and succ don't cut it for [0-9a-zA-Z]
  (0..9).each{|x|yield x.to_s}
  ('a'..'z').each{|x|yield x}
  ('A'..'Z').each{|x|yield x}
end
def alphaNumericX3
  alphaNumeric{ |a|
    alphaNumeric{ |b|
      alphaNumeric{ |c|
        yield a+b+c
      }
    }
  }
end
alphaNumericX3.each{|x|p x}

La mia domanda è 2 volte:

C'è un modo meno brutto e c'è un modo in cui alphaNumericX3 potrebbe essere definito dai parametri (alphaNumeric, 3) ?

PS Sono consapevole che potrei definire una nuova classe per intervallo. Ma questo non è sicuramente più breve. Se riesci a rendere questo blocco successivo più breve e più chiaro del blocco precedente, ti preghiamo di fare:

class AlphaNum
  include Comparable
  attr :length
  def initialize(s)
    @a=s.chars.to_a
    @length=@a.length
  end
  def to_s
    @a.to_s
  end
  def <=>(other)
    @a.to_s <=> other.to_s
  end
  def succ
    def inc(x,n)
      return AlphaNum.new('0'*(@length+1)) if x<0
      case n[x]
      when '9'
        n[x]='A'
      when 'Z'
        n[x]='a'
      when 'z'
        n[x]='0'
        return inc(x-1,n)
      else
        n[x]=n[x].succ
      end
      return AlphaNum.new(n.to_s)
    end
    inc(@length-1,@a.clone)
  end
end
# (AlphaNum.new('000')..AlphaNum.new('zzz')).each{|x|p x}
#  === alphaNumericX3.each{|x|p x}
È stato utile?

Soluzione

Usa Array # product :

alpha_numerics = ('0'..'9').to_a + ('a'..'z').to_a + ('A'..'Z').to_a
alpha_numerics
  .product(alpha_numerics, alpha_numerics)
  .map { |triplet| triplet.join('') }

Altri suggerimenti

class String
  def nextify
    case self
    when '9' then 'A'
    when 'Z' then 'a'
    when 'z' then '0'
    else self.succ
    end
  end
end

class AlphaNum
  def initialize(string)
    @string = string
  end

  def succ
    @string.split(//).inject("") { |s,n| s << n.nextify }
  end

  def method_missing(*args, &block)
    @string.send(*args, &block)
  end
end

a = AlphaNum.new("999")
puts a.succ #=> 'AAA'
Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top