ऊपरी बनाम निचला मामला


85

केस-असंवेदनशील तुलना करते समय, स्ट्रिंग को ऊपरी मामले या निचले मामले में बदलना अधिक कुशल है? क्या इससे भी फर्क पड़ता है?

इस SO पोस्ट में यह सुझाव दिया गया है कि C # ToUpper के साथ अधिक कुशल है क्योंकि "Microsoft ने इसे इस तरह से अनुकूलित किया है।" लेकिन मैंने यह तर्क भी पढ़ा है कि ToLower बनाम ToUpper को परिवर्तित करना इस बात पर निर्भर करता है कि आपके स्ट्रिंग्स में से किसमें अधिक है, और आमतौर पर स्ट्रिंग्स में अधिक कम केस वर्ण होते हैं जो ToLower को अधिक कुशल बनाता है।

विशेष रूप से, मैं जानना चाहूंगा:

  • क्या ToUpper या ToLower को ऑप्टिमाइज़ करने का एक तरीका है कि एक दूसरे से तेज़ हो?
  • क्या ऊपरी या निचले मामले के तार के बीच केस-असंवेदनशील तुलना करना तेजी से है, और क्यों?
  • क्या कोई प्रोग्रामिंग वातावरण हैं (उदाहरण। C, C #, पायथन, जो भी हो) जहां एक मामला स्पष्ट रूप से दूसरे से बेहतर है, और क्यों?

जवाबों:


90

केस-असंवेदनशील तुलना करने के लिए ऊपरी मामले या निचले मामले में परिवर्तित करना, कुछ संस्कृतियों, विशेष रूप से तुर्की की "दिलचस्प" विशेषताओं के कारण गलत है। इसके बजाय, उचित विकल्पों के साथ एक StringComparer का उपयोग करें।

MSDN के पास स्ट्रिंग हैंडलिंग पर कुछ महान दिशानिर्देश हैं । आप यह भी जांचना चाहेंगे कि आपका कोड तुर्की परीक्षण पास करता है या नहीं

EDIT: अध्यादेश के मामले-असंवेदनशील तुलना के आसपास नील की टिप्पणी पर ध्यान दें । यह पूरा क्षेत्र बहुत सुंदर है :(


15
हाँ StringComparer महान है, लेकिन इस सवाल का जवाब नहीं दिया गया था ... उन स्थितियों में जहाँ आप StringComparer का उपयोग नहीं कर सकते हैं जैसे कि एक स्ट्रिंग के खिलाफ एक swtich स्टेटमेंट; क्या मुझे स्विच में ToUpper या ToLower करना चाहिए?
19

7
ToUpper या ToLower का उपयोग करने के बजाय एक StringComparer और "if" / "और" का उपयोग करें।
जॉन स्कीट

5
जॉन, मुझे पता है कि निचले मामले में परिवर्तित करना गलत है, लेकिन मैंने नहीं सुना था कि अपरकेस में कनवर्ट करना गलत है। क्या आप एक उदाहरण या एक संदर्भ प्रदान कर सकते हैं? एमएसडीएन लेख जो आप से जुड़ा है, यह कहता है: "ऑर्डिनलइग्नोरकेस का उपयोग करके की गई तुलनात्मक रूप से दो कॉल की संरचना है: दोनों स्ट्रिंग तर्कों पर टूउपरइंटरवैंट को कॉल करना और एक साधारण तुलना करना।" "ऑर्डिनल स्ट्रिंग ऑपरेशंस" नामक अनुभाग में, यह कोड में इसे पुनर्स्थापित करता है।
नील

2
@ नील: दिलचस्प है, मैंने उस बिट को नहीं देखा था। एक क्रमिक मामले-असंवेदनशील तुलना के लिए, मुझे लगता है कि यह काफी उचित है। यह सब के बाद, कुछ लेने के लिए मिला है । सांस्कृतिक रूप से संवेदनशील मामला-असंवेदनशील तुलना के लिए, मुझे लगता है कि अभी भी कुछ अजीब व्यवहार के लिए जगह होगी। उत्तर में अपनी टिप्पणी इंगित करेंगे ...
जॉन स्कीट

4
@ ट्रायनको: मुझे लगता है कि मुख्य रूप से शुद्धता पर ध्यान केंद्रित करना महत्वपूर्ण है , इस बात के साथ कि गलत उत्तर प्राप्त करना आम तौर पर गलत जवाब पाने की तुलना में आमतौर पर बेहतर नहीं है (और कभी-कभी बदतर होता है)।
जॉन स्कीट

25

MSDN पर Microsoft से :

.NET फ्रेमवर्क में स्ट्रिंग्स का उपयोग करने के लिए सर्वोत्तम अभ्यास

स्ट्रिंग उपयोग के लिए सिफारिशें

  • का प्रयोग करें String.ToUpperInvariant के बजाय विधि String.ToLowerInvariant विधि जब आप तुलना के लिए तार सामान्य बनाते हैं।

क्यों? से माइक्रोसॉफ्ट :

अपरकेस को सामान्य करें

वर्णों का एक छोटा समूह है जिसे लोअरकेस में बदलने पर गोल यात्रा नहीं की जा सकती है।

ऐसे चरित्र का उदाहरण क्या है जो गोल यात्रा नहीं कर सकता है?

  • प्रारंभ : ग्रीक रो प्रतीक (U + 03f1) Sym
  • अपरकेस: राजधानी ग्रीक Rho (U + 03a1) Capital
  • लोअरकेस: स्मॉल ग्रीक Rho (U + 03c1) ρ

Ρ, Ρ , ρ

.NET फेल्ड

Original: ϱ
ToUpper: Ρ
ToLower: ρ

इसीलिए, यदि आपका केस असंवेदनशील तुलना करना चाहता है तो आप स्ट्रिंग्स को अपरकेस में परिवर्तित करते हैं, न कि लोअरकेस को।

इसलिए अगर आपको किसी एक को चुनना है, तो अपरकेस चुनें ।


और क्या कारण है?
भजन

@bjan इसका कारण यह है कि यह बुरा नहीं है।
इयान बॉयड

1
पात्रों का समूह क्या है? एक गोल यात्रा का क्या मतलब है?
जोहल

1
@johv लिंक से: "एक गोल यात्रा करने का अर्थ है पात्रों को एक स्थान से दूसरे स्थान पर परिवर्तित करना जो वर्ण डेटा को अलग-अलग रूप से प्रस्तुत करते हैं, और फिर रूपांतरित वर्णों से मूल वर्णों को ठीक से प्राप्त करने के लिए।" पात्रों का समूह क्या है? मुझे नहीं पता, लेकिन मैं iतुर्की के निचले हिस्से का अनुमान लगाने जा रहा हूं , जब आप इसका उपयोग करने के İबजाय, बन जाते Iहैं। इसके अलावा, हम अपरकेस Iबनने के लिए उपयोग किए जाते हैं i, लेकिन तुर्की में यह बन जाता है ı
इयान बॉयड

3
मूल प्रश्न के उत्तर पर वापस जाएं: एक ऊपरी मामले वाले संस्करण के लिए एक से कम मामले प्रकार जानने वाली भाषाएं हैं। जब तक आप जब जो प्रतिनिधित्व (ग्रीक में एक और उदाहरण का उपयोग करने के लिए नियमों को जानते हैं: छोटे सिग्मा पत्र, आप σ शब्द शुरू में या बीच में उपयोग करते हैं, शब्दों के अंत में ς (देखें en.wikipedia.org/wiki/Sigma ), आप सुरक्षित रूप से निचली स्थिति वाले संस्करण में वापस नहीं आ सकते।
एकॉनगुआ

19

MSDN के अनुसार स्ट्रिंग्स में पास होना और केस को अनदेखा करने के लिए तुलना करना अधिक कुशल है:

String.Compare (strA, strB, StringComparison.OrdinalIgnoreCase ) कॉल करने के बराबर ( लेकिन इससे भी तेज ) है

String.Compare (ToUpperInvariant (strA), ToUpperInvariant (strB), StringComparison.Ordinal)।

ये तुलना अभी भी बहुत तेज है।

बेशक, यदि आप एक स्ट्रिंग की बार-बार तुलना कर रहे हैं तो यह पकड़ नहीं हो सकता है।


12

अधिक लोअरकेस प्रविष्टियाँ करने के लिए रुझान वाले स्ट्रिंग्स के आधार पर, टॉलर को सैद्धांतिक रूप से तेज़ होना चाहिए (तुलना के बहुत सारे, लेकिन कुछ असाइनमेंट)।

C में, या प्रत्येक स्ट्रिंग के व्यक्तिगत-सुलभ तत्वों (जैसे C स्ट्रिंग या CL में STL के स्ट्रिंग प्रकार) का उपयोग करते समय, यह वास्तव में एक बाइट तुलना है - इसलिए तुलना UPPERकरना अलग नहीं है lower

यदि आप डरपोक थे और longइसके बजाय अपने तारों को सरणियों में लोड किया था, तो आपको पूरे स्ट्रिंग पर बहुत तेज़ तुलना मिलेगी क्योंकि यह एक बार में 4 बाइट्स की तुलना कर सकता है। हालाँकि, लोड समय इसे सार्थक नहीं बना सकता है।

आपको यह जानने की आवश्यकता क्यों है कि कौन सा तेज़ है? जब तक आप तुलनात्मक रूप से मीट्रिक बटलोड नहीं कर रहे हैं, तब तक एक जोड़ी साइकिल चलाना तेजी से पूरा निष्पादन की गति के लिए अप्रासंगिक है, और समय से पहले अनुकूलन की तरह लगता है :)


11
प्रश्न का उत्तर देने के लिए मुझे यह जानने की आवश्यकता है कि कौन सा तेज है: मुझे जानने की आवश्यकता नहीं है, मैं केवल जानना चाहता हूं। :) यह बस किसी को देखने का दावा करने का मामला है (जैसे "ऊपरी मामले के तार की तुलना तेज है!") और यह जानना चाहता है कि क्या यह वास्तव में सच है और / या उन्होंने यह दावा क्यों किया है।
परप्पा

1
यह समझ में आता है - मैं इस तरह से सामान पर बहुत उत्सुक हूँ :),
वॉरेन

C स्ट्रिंग्स के साथ, कन्वर्ट करने के लिए sऔर tलॉन्ग के सरणियों जैसे कि स्ट्रिंग्स बराबर iff हैं यदि ऐरे समान हैं तो आपको s और t तक चलना होगा जब तक कि आप समाप्ति '\0'वर्ण नहीं पाते (या फिर आप स्ट्रिंग्स के अंत में पिछले कचरे की तुलना कर सकते हैं) जो एक गैरकानूनी मेमोरी एक्सेस हो सकती है जो अपरिभाषित व्यवहार को आमंत्रित करती है)। लेकिन फिर एक-एक करके पात्रों के ऊपर चलते हुए तुलना क्यों नहीं करते? C ++ स्ट्रिंग्स के साथ, आप शायद लंबाई प्राप्त कर सकते हैं और .c_str(), एक डाली और लंबाई के long *एक उपसर्ग की तुलना कर सकते हैं .size() - .size()%(sizeof long)। मुझे लगता है, थोडा गड़बड़ लग रहा है।
जोनास कोल्कर

6

Microsoft ने अनुकूलित किया है ToUpperInvariant(), नहीं ToUpper()। अंतर यह है कि आक्रमणकारी अधिक संस्कृति के अनुकूल है। यदि आपको स्ट्रिंग्स पर केस-असंवेदनशील तुलना करने की आवश्यकता है, जो संस्कृति में भिन्न हो सकती है, तो Invariant का उपयोग करें, अन्यथा अपरिवर्तनीय रूपांतरण का प्रदर्शन मायने नहीं रखना चाहिए।

मैं नहीं कह सकता कि क्या ToUpper () या ToLower () तेज़ है। मैंने कभी इसकी कोशिश नहीं की, क्योंकि मेरे पास कभी ऐसी स्थिति नहीं थी जहां प्रदर्शन इतना मायने रखता था।


अगर Microsoft ने अपरकेस प्रदर्शन करने के लिए कोड को अनुकूलित किया है, तो यह इसलिए है क्योंकि अपरकेस अक्षरों के लिए ASCII कोड केवल दो अंकों में 65 - 90 है जबकि ASCII कोड लोअरकेस अक्षर 97 -122 है जिसमें 3 अंक (अधिक प्रसंस्करण की आवश्यकता है) है?
मेडो मेडो

3
@ मेडो मुझे अनुकूलन के सटीक कारणों को याद नहीं है, लेकिन 2 बनाम 3 अंक लगभग निश्चित रूप से कारण नहीं है क्योंकि सभी अक्षरों को बाइनरी नंबर के रूप में संग्रहीत किया जाता है, इसलिए दशमलव अंकों का वास्तव में अर्थ नहीं है कि वे संग्रहीत किए गए तरीके के आधार पर हैं।
डेन हर्बर्ट

4

यदि आप C # में स्ट्रिंग की तुलना कर रहे हैं तो इसका उपयोग करना काफी तेज है। दोनों स्ट्रिंग को ऊपरी या निचले मामले में परिवर्तित करने के बजाय ()। उपयोग करने के लिए एक और बड़ा प्लस .quals () यह है कि 2 नए ऊपरी / निचले केस स्ट्रिंग्स के लिए अधिक मेमोरी आवंटित नहीं की गई है।


4
और एक बोनस के रूप में, यदि आप सही विकल्प चुनते हैं, तो यह वास्तव में आपको सही परिणाम देगा :)
जॉन स्कीट

1

यह वास्तव में कभी बात नहीं करना चाहिए। ASCII वर्णों के साथ, यह निश्चित रूप से मायने नहीं रखता है - यह केवल कुछ तुलनाओं और दिशा के लिए थोड़ा फ्लिप है। यूनिकोड थोड़ा और अधिक जटिल हो सकता है, क्योंकि कुछ ऐसे पात्र हैं जो अजीब तरीकों से मामले को बदलते हैं, लेकिन वास्तव में कोई अंतर नहीं होना चाहिए जब तक कि आपका पाठ उन विशेष वर्णों से भरा न हो।


1

इसे सही करते हुए, एक छोटा, तुच्छ गति लाभ होना चाहिए यदि आप निचले मामले में परिवर्तित करते हैं, लेकिन यह है, जैसा कि कई ने संकेत दिया है, संस्कृति निर्भर है और फ़ंक्शन में इनहेरिट नहीं की गई है, लेकिन स्ट्रिंग्स में आप परिवर्तित करते हैं (बहुत कम अक्षर अक्षर) मेमोरी के लिए कुछ असाइनमेंट का मतलब है) - यदि आपके पास ऊपरी मामले के बहुत सारे अक्षरों के साथ एक स्ट्रिंग है, तो ऊपरी मामले में परिवर्तित करना तेज है।


0

निर्भर करता है। जैसा कि ऊपर कहा गया है, केवल समान ASCII, इसका समान है। .NET में, स्ट्रिंग के बारे में पढ़ें और उपयोग करें । i18n सामान (भाषा संस्कृतियों और यूनिकोड) के लिए इसका सही उपयोग करें । यदि आप इनपुट की संभावना के बारे में कुछ भी जानते हैं, तो अधिक सामान्य मामले का उपयोग करें।

याद रखें, यदि आप कई स्ट्रिंग कर रहे हैं तो लंबाई की तुलना करना एक उत्कृष्ट पहला भेदभाव है।


-2

यदि आप शुद्ध ASCII में काम कर रहे हैं, तो इससे कोई फर्क नहीं पड़ता। यह सिर्फ एक OR x, 32 बनाम a और x, 224 है। यूनिकोड, मुझे कोई पता नहीं है ...


4
यह पूरी तरह से गलत है - 32 के साथ OR'ING केवल AZ और वर्ण 64-127 के लिए काम करता है; यह अन्य सभी पात्रों पर शिकंजा कसता है। 32 के साथ AND'ing और भी गलत है - परिणाम हमेशा 0 (शून्य) या 32 (स्थान) होगा।
एडम रोसेनफील्ड
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.