RoR

2009-06-11 9 views
14

में यूटीएफ -8 स्ट्रिंग्स को सॉर्ट करना मैं रूबी पर रूबी में यूटीएफ -8 तारों को सॉर्ट करने का 'उचित' तरीका समझने की कोशिश कर रहा हूं।RoR

मेरे आवेदन में, मेरे पास एक चुनिंदा बॉक्स है जो देशों के साथ आबादी वाला है। चूंकि मेरा आवेदन स्थानीयकृत है, प्रत्येक मौजूदा लोकेल में एक देश.आईएमएल फ़ाइल है जो देश के आईडी को उस देश के स्थानीय नाम से संबंधित करती है। मैं yml फ़ाइल में तारों को मैन्युअल रूप से सॉर्ट नहीं कर सकता क्योंकि मुझे आईडी को सभी लोकेशंस में सुसंगत होने की आवश्यकता है।

क्या मैंने किया है एक ascii_name विधि है जो उनके ascii बराबर उच्चारण चिह्न और गैर-लैटिन वर्णों में कनवर्ट करने unidecode मणि का उपयोग करता है बनाने के (उदाहरण के लिए, "Afeganistão" बन जाएगा "Afeganistao") उस पर तरह है, और फिर:

require 'unidecode' 

class Country 
    def ascii_name 
    Unidecoder.decode(name).gsub("[?]", "").gsub(/`/, "'").strip 
    end 
end 

Country.all.sort_by(:&ascii_name) 

हालांकि, इस के साथ स्पष्ट मुद्दे हैं:

  • यह नहीं कर सकते हैं ठीक से तरह गैर-लैटिन स्थलों, के रूप में वहाँ एक सीधा अनुरूप लैटिन चरित्र नहीं हो सकता।
  • यह एक पत्र और उस पत्र के सभी स्वराघात रूप के बीच कोई फर्क (हां, तो उदाहरण के लिए, एक और एक विनिमेय हो जाते हैं) बनाता है

किसी को भी एक बेहतर तरीका है कि मैं अपने तार को सॉर्ट कर सकता है पता है?

उत्तर

8

http://github.com/grosser/sort_alphabetical

यह मणि की मदद करनी चाहिए। यह sort_alphabetical और sort_alphabetical_by एनंबरबल करने के तरीकों को जोड़ता है।

+0

धन्यवाद, यह बिल्कुल सही तरह का प्लगइन था जिसे मैं ढूंढ रहा था! –

+1

यह प्लगइन एनएफडी अपघटन http://en.wikipedia.org/wiki/Unicode_equivalence#Normal_forms पर निर्भर करता है और कुछ मामलों में विफल रहता है। सभी diacritic पात्र इस तरह से विघटित नहीं किया जा सकता है (उदाहरण के लिए पोलिश पत्र Ł नहीं कर सकते हैं)। – skalee

+1

@skalee क्या आपके पास कोई सुझाव है कि पॉलिश वर्णों के साथ utf-8 तारों को सही ढंग से कैसे व्यवस्थित किया जाए? – mdrozdziel

1

जाने के कुछ तरीके हैं। आप हेक्स तार करने के लिए UTF तार बदलने और फिर उन्हें सुलझाने के लिए चाहते हो सकता है:

s.split(//).collect { |x| x.unpack('U').to_s }.join 

या आप पुस्तकालय iconv उपयोग कर सकते हैं। यह के बारे में पढ़ें और प्रयोग यह के रूप में उपयुक्त (dzone से):

#add this to environment.rb 
#call to_iso on any UTF8 string to get a ISO string back 
#example : "Cédez le passage aux français".to_iso 

class String 
    require 'iconv' #this line is not needed in rails ! 
    def to_iso 
    Iconv.conv('ISO-8859-1', 'utf-8', self) 
    end 
end 
+1

एचएम, हेक्स वैल्यू द्वारा क्रमबद्ध करना मेरे तारों को वर्णानुक्रम में डालता प्रतीत होता है, लेकिन मुझे वास्तव में यह समझ में नहीं आता कि यह कैसे काम कर रहा है, क्या आप इसे समझा सकते हैं? इसके अलावा, यह अभी भी ए से पहले सॉर्ट कर रहा है, जो मेरे पीछे की ओर लगता है। –

+4

यह भी देखें: यूनिकोड सॉर्टिंग लोकेल पर निर्भर करती है! विभिन्न देशों के अपने शब्दकोश में एक अलग आदेश है। –

+0

ठीक है, हेक्स में कनवर्ट करने से आपको एक ऑर्डरिंग मिलती है जो सॉर्ट फ़ंक्शंस द्वारा बेहतर समझा जाता है। मैं 2 या 3 दशमलव स्थानों पर स्वरूपित हेक्स मानों का उपयोग करके थोड़ा सा प्रयोग करूंगा। या प्रत्येक चरित्र के लिए दशमलव मान भी उपयोग करें। मैं खुद एक बड़ा यूटीएफ उपयोगकर्ता नहीं हूं, लेकिन यह रटर की टिप्पणियों से दिखाई देता है कि आप जो करने की कोशिश कर रहे हैं उसका सटीक उत्तर नहीं है। –

-2

आप अपने देश तार से प्रत्येक के लिए mb_chars विधि तक पहुँचने की कोशिश की है? mb_chars एक प्रॉक्सी है जो ActiveSupport जोड़ता है जो सभी String विधियों के यूनिकोड सुरक्षित संस्करणों को परिभाषित करता है। यदि तुलनित्र यूनिकोड-जागरूक है तो सॉर्टिंग सही ढंग से काम करनी चाहिए।

+1

mb_chars का उपयोग करने में समस्या सीधे सॉर्टिंग के समान है; क्योंकि चरित्र सेट ए-जेड में पहले आता है, उच्चारण वर्ण सही स्थान में क्रमबद्ध नहीं होंगे। –

0

जो आप करने की कोशिश कर रहे हैं वह एक बहुत गन्दा प्रस्ताव है। सभी यूनिकोड वर्णों पर पारदर्शी लिप्यंतरण करने का कोई तरीका नहीं है क्योंकि डिग्राफ का अर्थ लोकेल से लोकेल में बदल जाता है, और तार बड़े हो सकते हैं (यदि आप कहते हैं कि आप 10 चीनी प्रतीकों को उनके फोनेटिक समकक्षों के साथ प्रतिस्थापित करते हैं)। वहां मत जाओ

आप पहले स्थान पर लिप्यंतरित नाम क्यों चाहते हैं? यूआरएल के लिए? ब्राउज़र अब यूनिकोड यूआरएल को सौदा करते हैं, इसलिए आप पतली हवा से एक बड़ी समस्या का आविष्कार कर रहे हैं। यदि आपको आईडी की आवश्यकता है, तो प्रति देश एक स्थिर संख्यात्मक आईडी शामिल करने के लिए अपनी सूचियों को प्रीप्रोसेस करें और इसे पहचानकर्ता के रूप में उपयोग करें। या देश के अंग्रेजी नाम को पहचानकर्ता के रूप में सहेजें (आप लोकेल-जागरूक आईएसओ देश सूचियों को मुफ्त में डाउनलोड कर सकते हैं)।

यदि आप वास्तव में यूनिकोड के लिए अच्छा लिप्यंतरण चाहते हैं (और यह इस मामले में आप जो चाहते हैं वह नहीं है) आईबीएम आईसीयू पुस्तकालयों को देखें, उनके लिए एक निष्क्रिय मणि है।

+0

प्रश्न स्पष्ट रूप से स्थानीय तारों को क्रमबद्ध करने के बारे में पूछता है। एक लिप्यंतरण के बारे में नहीं। –

1

एकमात्र कामकाजी समाधान जो मैंने पाया है (कम से कम रुबी 1.8 के लिए क्योंकि रूबी 1.9 को यूनिकोड को बेहतर तरीके से संभालना चाहिए) Unicode by Yoshida Masato है। आप वहां Unicode.strcmp विधि पा सकते हैं।

संपादित करें: क्षमा करें, यह समाधान एनएफडी अपघटन के साथ-साथ इसकी सभी सीमाओं का भी उपयोग करता है। अब केवल समस्या यह है कि इस equalizes "एक" के साथ 'ए' (है

Country.all.sort_by do |country| 
    ActiveSupport::Inflector.transliterate country.name 
end 

:

4

एकमात्र समाधान मैं अब तक पाया है ActiveSupport::Inflector.transliterate(string) उपयोग करने के लिए ASCII लोगों और तरह के साथ यूनिकोड वर्ण को बदलने के लिए है डीआईएन 5007-1) और मैं "अल्बानियन" से पहले "मिस्र" के साथ समाप्त हुआ, जबकि मैं उम्मीद करता हूं कि यह दूसरी तरफ होगा। शुक्र है कि लिप्यंतरण वर्णों को प्रतिस्थापित करने के तरीके के बारे में विन्यास योग्य है। प्रलेखन

देखें: http://api.rubyonrails.org/classes/ActiveSupport/Inflector.html#method-i-transliterate

+0

क्या आप केवल स्थानीय लोगों के तारों के अनुसार तारों को सॉर्ट करने के लिए स्ट्रिंग्स या विधि को टाइप करने के लिए एक विधि ढूंढ रहे हैं? – toro2k

+0

एक लोकेल collation द्वारा नवीनतम, सॉर्ट तार। – Kostas

+0

उचित संयोजन के साथ भी (मुझे लगता है कि 'de_DE.UFT8') यह सामान्य है कि * मिस्र * * अल्बानीन * से पहले आता है। – toro2k

10

रूबी पात्रों में से बाइट मूल्यों पर आधारित स्ट्रिंग तुलना peforms:

%w[à a e].sort 
# => ["a", "e", "à"] 

ठीक से वातावरण के अनुसार तार मुक़ाबला करने के लिए, ffi-icu मणि इस्तेमाल किया जा सकता:

require "ffi-icu" 

ICU::Collation.collate("it_IT", %w[à a e]) 
# => ["a", "à", "e"] 

ICU::Collation.collate("de", %w[a s x ß]) 
# => ["a", "s", "ß", "x"] 

एक विकल्प के रूप में:

collator = ICU::Collation::Collator.new("it_IT") 
%w[à a e].sort { |a, b| collator.compare(a, b) } 
# => %w[a à e] 

अद्यतन स्थानीय नियमों के अनुसार तारों को कैसे व्यवस्थित करना चाहिए यह जांचने के लिए आईसीयू परियोजना this nice tool प्रदान करती है।

+0

एकमात्र चीज जो मुझे "एफएफआई-आईसीयू" के बारे में पसंद नहीं है वह यह है कि यह "libicu" पर निर्भर करता है। लेकिन मुझे लगता है कि यह यूनिक्स सिस्टम पर सुंदर सर्वव्यापी है, है ना? – Kostas

+0

आमतौर पर यह डिफ़ॉल्ट रूप से स्थापित नहीं है, लेकिन यह लगभग किसी भी सिस्टम पर उपलब्ध है। – toro2k

संबंधित मुद्दे

 संबंधित मुद्दे