2015-10-22 19 views
9

Bir sürüm listesini Ruby'de nasıl sıralayabilirim? Doğal sıralama hakkında bir şeyler gördüm, ama bunun ötesinde bir adım.Sürüm sırası (alpha, bici, vb.) Ruby içinde

input = ['10.0.0b12', '10.0.0b3', '10.0.0a2', '9.0.10', '9.0.3'] 

Ben naturally taş ile yapmak neredeyse edebilirsiniz:

Girdi böyle dizeleri bir demet

require 'naturally' 
Naturally.sort(input) 
=> ["9.0.3", "9.0.10", "10.0.0a2", "10.0.0b12", "10.0.0b3"]  

Sorun: 10.0.0b3 10.0.0b12 sonra sıralanır; İlk önce 10.0.0b3 olmalıdır.

Herkesin bir yolu var mı? Diğer diller de yardımcı oluyor! Eğer "her basamak segmente göre sıralama" olarak nitelendirildiği, varsa

+1

Bunlar son derece atipik sürüm dizeleridir. Yetersiz bir çözüm bulmanız olası değildir; kendi yazman gerekir. – meagar

+0

Semantik Sürüm'ü kullanmak için değiştirdim. Bu daha tipik. –

+0

@MusashiAharon Bu oldukça Semantik Sürüm oluşturma değil. Bunun için b12'nin b3'nün, önce bir '-' ile olmasını istersiniz. – Ajedi32

cevap

19

Yakut gemileri, Bu sürümler hakkında bilgi sahibi olanlar:

ar = ['10.0.0b12', '10.0.0b3', '10.0.0a2', '9.0.10', '9.0.3'] 

p ar.sort_by { |v| Gem::Version.new(v) } 
# => ["9.0.3", "9.0.10", "10.0.0a2", "10.0.0b3", "10.0.0b12"] 
+2

Güzel. Değeri için - bu "alfabe" ve "beta" sadece alfabetik olarak ele alır. Yani, ['9.0.10rc2', '9.0.10', '9.0.10rc1', '9.0.10a', '9.0.10test'] '[" 9.0.10a "," 9.0.10rc1 "değerleri "9.0.10rc2", "9.0.10test", "9.0.10"] '. "Alpha/beta/pre-release/rc/release" harfinin alfabetik olarak akabildiği için yeterli olmalı, ancak verileriniz bundan çok uzaksa, ilginç olabilir. – DreadPirateShawn

+0

nasıl çalıştığını oldukça ilginç: https://github.com/rubygems/rubygems/blob/1aa8033952d4eda5ca131039822f9548166ab507/lib/rubygems/version.rb#L336-L361 – Anthony

1

, o zaman şu senin örneğin girişi idare edecek yukarıda: is

input.map{ |ver| ver.split(%r{[^\d]+}).map(&:to_i) }.zip(input).sort.map(&:last) 
=> ["9_0", "9_1", "10_0b3", "10_0b12"] 

, her değer için

  • , örneğin 10_0b3
  • olmayan basamaklı, herhangi bir karakter uzunluğuna bölünmüş, örneğin ["10","0","3"] her basamaklı kademeli bir tamsayı
  • döküm, örneğin [10,0,3]
  • orijinal girişi ile fermuar, verim [[[10, 0, 12], "10_0b12"], [[10, 0, 3], "10_0b3"], [[9, 0], "9_0"], [[9, 1], "9_1"]]
  • [10,0,3] < [10,0,12] sayesinde
  • sıralama

Şimdi, her bir işlenmiş sıralanabilir değerine karşılık gelen orijinal girdi değeri her bir elemanın, son değer elde Bu, hala oldukça özel - "9_0a" vs "9_0b" kadar basit sürüm numaraları ele alınmaz, her ikisi de [9,0] gibi görünecektir - bu yüzden daha fazla düzeltmeniz gerekebilir, ancak umarım Bu sizi geçerli bir yoldan başlar.

DÜZENLEME: değişmiş Örnek girişi yukarıda, bu yüzden haneli eşleştirme açgözlü olduğunu ve birlikte hala tutar emin olmak için regex'i değiştirdi: Gem sınıfıyla

irb(main):018:0> input = ['10.0.0b12', '10.0.0b3', '9.0.10', '9.0.3'] 
=> ["10.0.0b12", "10.0.0b3", "9.0.10", "9.0.3"] 
irb(main):025:0> input.map{ |ver| ver.split(%r{[^\d]+}).map(&:to_i) }.zip(input).sort.map(&:last) 
=> ["9.0.3", "9.0.10", "10.0.0b3", "10.0.0b12"] 
+0

Bu yardımcı olur, ancak betalar tek olası son değildir. Ayrıca '10 .0.0a2 'gibi alfalara da sahip olabiliriz ya da '10 .0.0rc1' gibi adayları serbest bırakabiliriz. Bunlar diğerleri ile yan yana ise, sıralama bozulur. –