আমি কীভাবে কেস-সংবেদনশীল স্ট্রিং তুলনা করব?


573

পাইথনে আমি কীভাবে সংবেদনশীল স্ট্রিং তুলনা করতে পারি?

আমি খুব সাধারণ এবং পাইথোনিক উপায়ে ব্যবহার করে একটি রেপোজিটরি স্ট্রিংয়ের সাথে নিয়মিত স্ট্রিংগুলির তুলনা করতে চাই। আমি নিয়মিত পাইথন স্ট্রিংগুলি ব্যবহার করে স্ট্রিং দিয়ে হ্যাশ করা একটি ডিকের মানগুলি সন্ধান করার দক্ষতা অর্জন করতে চাই।

উত্তর:


595

ASCII স্ট্রিং ধরে নিচ্ছি:

string1 = 'Hello'
string2 = 'hello'

if string1.lower() == string2.lower():
    print("The strings are the same (case insensitive)")
else:
    print("The strings are NOT the same (case insensitive)")

71
এটি সবসময় কাজ করে না। প্রসারণের জন্য বিবেচনা করুন যে দুটি গ্রীক সিগমাস রয়েছে, একজন কেবলমাত্র শেষে ব্যবহৃত হয়। স্ট্রিং Σίσυφος ("সিসিফোস" বা আরও ভাল "সাইফস") তিনটি রয়েছে: সামনে বড় হাতের অক্ষর, শেষে ছোট হাতের চূড়ান্ত এবং তৃতীয় অবস্থানে লোয়ারকেস ননফাইনাল। যদি আপনার দুটি স্ট্রিং থাকে Σίσυφοςএবং ΣΊΣΥΦΟΣতবে আপনার পন্থাটি ব্যর্থ হয়, কারণ সেগুলি সংবেদনশীলভাবে একই ক্ষেত্রে বলে মনে করা হয়।
tchrist

51
@ শেষ দু'জন মন্তব্যকারী: আমি মনে করি এটি উভয় স্ট্রিংকে আসকি স্ট্রিং বলে ধরে নেওয়া ঠিক হবে। আপনি যদি কিছুটা উত্তেজনাপূর্ণ কোনও কিছুর উত্তর খুঁজছেন তবে আমি নিশ্চিত যে এটি সেখানে রয়েছে (বা আপনি এটি জিজ্ঞাসা করতে পারেন)।
হারলে হলকম্ব

16
সমস্যা: 'ß'.lower() == 'SS'.lower()মিথ্যা।
কেনেটিএম

11
গ্রীক অক্ষর একমাত্র বিশেষ ক্ষেত্রে নয়! ইউএস ইংরেজিতে, "i" (00 u0069) অক্ষরটি "I" (\ u0049) অক্ষরের ছোট হাতের সংস্করণ। তবে তুর্কি ("টিআর-টিআর") বর্ণমালায় একটি "আই উইথ ডট" অক্ষর "İ" (0 u0130) অন্তর্ভুক্ত রয়েছে, যা "আই" এর মূলধন সংস্করণ এবং "আমি" "আমি ছাড়া" এর ক্যাপটিক্যাল সংস্করণ একটি বিন্দু "অক্ষর," ı "(0 u0131)।
Gqqnbig

20
@ হারলেহলকম্বে স্ট্রিংগুলি অসকি বলে ধরে নেওয়া নিরাপদ (বা ফর্সা) কীভাবে? প্রশ্নটি সুনির্দিষ্ট করে নি এবং যদি কোনও স্ট্রিং প্রবেশ করে বা ব্যবহারকারীর কাছে প্রদর্শিত হয়, তবে আপনার উচিত আন্তর্জাতিকীকরণকে সমর্থন করা। নির্বিশেষে, নতুন প্রোগ্রামাররা এটি পড়বে এবং আমাদের তাদের সত্যিকারের সঠিক উত্তর দেওয়া উচিত।
ইথান রেসোর

529

সংবেদনশীল উপায়ে স্ট্রিংগুলির তুলনা তুচ্ছ মনে হয়, তবে তা হয় না। আমি পাইথন 3 ব্যবহার করব, যেহেতু পাইথন 2 এখানে অনুন্নত রয়েছে।

প্রথম যে বিষয়টি লক্ষ্যণীয় তা হ'ল ইউনিকোডে কেস-অপসারণ রূপান্তরগুলি তুচ্ছ নয়। এর জন্য পাঠ্য রয়েছে text.lower() != text.upper().lower()যেমন "ß":

"ß".lower()
#>>> 'ß'

"ß".upper().lower()
#>>> 'ss'

তবে ধরা যাক আপনি নির্বিশেষে তুলনা করতে চেয়েছিলেন "BUSSE"এবং "Buße"। হেক, আপনি সম্ভবত তুলনা করতে "BUSSE"এবং "BUẞE"সমান করতে চান - এটি নতুন মূলধন ফর্ম। প্রস্তাবিত উপায়টি হ'ল casefold:

Str। কেসফোল্ড ()

স্ট্রিংয়ের কেসফোল্ডড কপিটি ফিরিয়ে দিন। কেসফোল্ডড স্ট্রিংগুলি কেসলেস ম্যাচের জন্য ব্যবহার করা যেতে পারে।

কেসফোল্ডিং হ্রাস করা সমান তবে আরও আক্রমণাত্মক কারণ এটি স্ট্রিংয়ের ক্ষেত্রে সমস্ত ক্ষেত্রে পার্থক্যগুলি সরিয়ে ফেলার উদ্দেশ্যে is [...]

শুধু ব্যবহার করবেন না lower। যদি casefoldউপলভ্য না হয় .upper().lower()তবে করা সাহায্য করে (তবে কেবল কিছুটা)।

তারপরে আপনার উচ্চারণগুলি বিবেচনা করা উচিত। যদি আপনার হরফ রেন্ডারার ভাল হয় "ê" == "ê"তবে আপনি সম্ভবত ভাবেন - তবে তা হয় না:

"ê" == "ê"
#>>> False

এটি কারণ কারণের পরে অ্যাকসেন্ট একটি সংমিশ্রিত চরিত্র।

import unicodedata

[unicodedata.name(char) for char in "ê"]
#>>> ['LATIN SMALL LETTER E WITH CIRCUMFLEX']

[unicodedata.name(char) for char in "ê"]
#>>> ['LATIN SMALL LETTER E', 'COMBINING CIRCUMFLEX ACCENT']

এটির সাথে মোকাবিলা করার সহজ উপায় unicodedata.normalize। আপনি সম্ভবত ব্যবহার করতে চান NFKD নিয়মমাফিককরণ কিন্তু ডকুমেন্টেশন চেক করুন মুক্ত মনে। তারপরে একজন করে

unicodedata.normalize("NFKD", "ê") == unicodedata.normalize("NFKD", "ê")
#>>> True

শেষ করতে, এখানে এটি ফাংশনগুলিতে প্রকাশ করা হয়েছে:

import unicodedata

def normalize_caseless(text):
    return unicodedata.normalize("NFKD", text.casefold())

def caseless_equal(left, right):
    return normalize_caseless(left) == normalize_caseless(right)

8
গ্রহণের ক্ষেত্রে আপনার সমস্ত স্ট্রিংগুলিকে স্বাভাবিক করা একটি আরও ভাল সমাধান, তবে আপনি কেবল x.casefold() == y.casefold()কেস-সংবেদনশীল তুলনা (এবং আরও গুরুত্বপূর্ণভাবে x == yকেস-সংবেদনশীলদের জন্য) করতে পারেন।
abarnert

3
@ বাবার্ন্ট প্রকৃতপক্ষে, প্রেক্ষাপটের উপর নির্ভর করে - কখনও কখনও উত্সটি অক্ষত রেখে দেওয়া ভাল তবে সম্মুখের স্বাভাবিকীকরণ পরবর্তী কোডটি আরও সহজ করে তুলতে পারে।
Veedrac 12

3
@ উইড্রাক: আপনি ঠিক বলেছেন, এটি সর্বদা যথাযথ নয়; যদি আপনার মূল উত্সটি অপরিবর্তিত অবস্থায় আউটপুট করতে সক্ষম করা প্রয়োজন (যেমন, আপনি লিনাক্সে ফাইলের নামগুলি নিয়ে কাজ করছেন, যেখানে এনকেএফসি এবং এনকেএফডি উভয়ই অনুমোদিত এবং স্পষ্টতই আলাদা বলে মনে করা হচ্ছে), স্পষ্টতই আপনি এটিকে ইনপুটটিতে রূপান্তর করতে পারবেন না ...
1515

7
ইউনিকোড স্ট্যান্ডার্ড বিভাগ 3.13 এর কেসলেস তুলনার জন্য অন্য দুটি সংজ্ঞা রয়েছে: NFD(toCasefold(NFD(str)))উভয় পক্ষের (D146, ক্যানোনিকাল) এবং উভয় পক্ষের (D147, সামঞ্জস্য) NFKD(toCasefold(NFKD(toCasefold(NFD(X)))))। এটি জানিয়েছে যে অভ্যন্তরীণটি NFDকেবলমাত্র একটি নির্দিষ্ট গ্রীক উচ্চারণের চরিত্রটি পরিচালনা করতে পারে। আমার ধারণা এগুলি সবই প্রান্তের মামলাগুলির বিষয়ে।

2
এবং চেরোকি বর্ণমালার সাথে কিছুটা মজা করুন, যেখানে কেসফোল্ড () বড় হাতের নাগালে চলে যায়: >>> "ᏚᎢᎵᎬᎢᎬᏒ"। উপরের () 'ᏚᎢᎵᎬᎢᎬᏒ' >>> "" ᏚᎢᎵᎬᎢᎬᏒ "। নিম্ন () 'ꮪꭲꮅꭼꭲꭼꮢ' >>>" ᏚᎢᎵᎬᎢᎬᏒ " .cesfold () 'ᏚᎢᎵᎬᎢᎬᏒ' >>>
bortzmeyer

60

পাইথন 2 ব্যবহার .lower()করে প্রতিটি স্ট্রিং বা ইউনিকোড অবজেক্টে কল করা ...

string1.lower() == string2.lower()

... বেশিরভাগ সময় কাজ করবে, তবে প্রকৃতপক্ষে সেই পরিস্থিতিটি কার্যকর হয় না যা @ ক্রাইস্ট বর্ণনা করেছেন

ধরে আমরা একটি ফাইল আছে বলা unicode.txtদুটি স্ট্রিং ধারণকারী Σίσυφοςএবং ΣΊΣΥΦΟΣ। পাইথন 2 সহ:

>>> utf8_bytes = open("unicode.txt", 'r').read()
>>> print repr(utf8_bytes)
'\xce\xa3\xce\xaf\xcf\x83\xcf\x85\xcf\x86\xce\xbf\xcf\x82\n\xce\xa3\xce\x8a\xce\xa3\xce\xa5\xce\xa6\xce\x9f\xce\xa3\n'
>>> u = utf8_bytes.decode('utf8')
>>> print u
Σίσυφος
ΣΊΣΥΦΟΣ

>>> first, second = u.splitlines()
>>> print first.lower()
σίσυφος
>>> print second.lower()
σίσυφοσ
>>> first.lower() == second.lower()
False
>>> first.upper() == second.upper()
True

Σ চরিত্রটির দুটি ছোট ছোট রূপ রয়েছে ς এবং σ, এবং .lower()এগুলি কেস-সংবেদনশীলতার সাথে তুলনায় সহায়তা করবে না।

যাইহোক, পাইথন 3 হিসাবে, তিনটি ফর্মই ς এ সমাধান করবে এবং উভয় স্ট্রিংয়ে লোয়ার () কল করা সঠিকভাবে কাজ করবে:

>>> s = open('unicode.txt', encoding='utf8').read()
>>> print(s)
Σίσυφος
ΣΊΣΥΦΟΣ

>>> first, second = s.splitlines()
>>> print(first.lower())
σίσυφος
>>> print(second.lower())
σίσυφος
>>> first.lower() == second.lower()
True
>>> first.upper() == second.upper()
True

সুতরাং আপনি যদি গ্রীক ভাষায় তিনটি সিগমাসের মতো এজ-কেস সম্পর্কে যত্নশীল হন তবে পাইথন 3 ব্যবহার করুন।

(রেফারেন্সের জন্য, পাইথন ২.7.৩ এবং পাইথন ৩.৩.০ বি 1 উপরোক্ত দোভাষীর মুদ্রণগুলিতে দেখানো হয়েছে।)


20
তুলনাটিকে আরও দৃust় করতে পাইথন ৩.৩ দিয়ে শুরু করে আপনি কেসফোল্ড ব্যবহার করতে পারেন (যেমন, ফার্স্টক্যাসফোল্ড (), ফার্স্টক্যাসফোল্ড () == সেকেন্ডক্যাসফোল্ড ())। পাইথন 2 এর জন্য আপনি পাইআইসিইউ ব্যবহার করতে পারেন (এটিও দেখুন: আইসু
প্রজেক্ট.আর.পায়ারফ

42

ইউনিকোড স্ট্যান্ডার্ডের বিভাগ 3.13 কেসলেস ম্যাচিংয়ের জন্য অ্যালগরিদমকে সংজ্ঞায়িত করে।

X.casefold() == Y.casefold() পাইথন 3 এ "ডিফল্ট কেসলেস ম্যাচিং" (ডি 144) প্রয়োগ করে।

কেসফোল্ডিং সমস্ত ক্ষেত্রে স্ট্রিংগুলির স্বাভাবিকীকরণ সংরক্ষণ করে না এবং তাই স্বাভাবিককরণের প্রয়োজন ( 'å'বনাম 'å')। D145 "ক্যানোনিকাল কেসলেস ম্যাচিং" উপস্থাপন করেছে:

import unicodedata

def NFD(text):
    return unicodedata.normalize('NFD', text)

def canonical_caseless(text):
    return NFD(NFD(text).casefold())

NFD() U + 0345 অক্ষর জড়িত খুব বিরল প্রান্ত ক্ষেত্রে দু'বার বলা হয়।

উদাহরণ:

>>> 'å'.casefold() == 'å'.casefold()
False
>>> canonical_caseless('å') == canonical_caseless('å')
True

এছাড়া যেমন ক্ষেত্রে সামঞ্জস্য caseless ম্যাচিং (D146) হয় '㎒'(ইউ + + 3392) এবং "আইডেন্টিফায়ার caseless ম্যাচিং" প্রক্রিয়া সহজ করার জন্য এবং কার্যকর করে তুলুন অভিন্ন পরিচয় caseless ম্যাচিং


3
এটি পাইথন 3-এর সেরা উত্তর, কারণ পাইথন 3 ইউনিকোড স্ট্রিং ব্যবহার করে এবং উত্তরটি কীভাবে ইউনিকোড স্ট্যান্ডার্ড কেসলেস স্ট্রিং ম্যাচিং সংজ্ঞায়িত করে তা বর্ণনা করে।
সের্গেইকোলসনিকভ

দুর্ভাগ্যক্রমে, পাইথন ৩.6 হিসাবে, casefold()ফাংশনটি বড় হাতের আই এবং ডটেড বড়হাঁস I এর বিশেষ কেস চিকিত্সা কেস ফোল্ডিং বৈশিষ্ট্যে বর্ণিত হিসাবে প্রয়োগ করে না । অতএব, তুর্কি ভাষার শব্দগুলিতে এই বর্ণগুলি ধারণ করে এমন তুলনা ব্যর্থ হতে পারে। উদাহরণস্বরূপ, canonical_caseless('LİMANI') == canonical_caseless('limanı')অবশ্যই ফিরতে হবে Trueতবে এটি ফিরে আসে False। বর্তমানে পাইথনে এটি মোকাবেলার একমাত্র উপায় হ'ল কেসফোল্ড র‌্যাপার লেখা বা বাইরের ইউনিকোড লাইব্রেরি যেমন পাইআইসিইউ ব্যবহার করা।
সের্গেইকোলস্নিকভ

@ সার্জিকিলেসনিকভ। কেসফোল্ড () যতদূর আমি বলতে পারি সেভাবে আচরণ করে। স্ট্যান্ডার্ড থেকে: "ডিফল্ট কেসিং অপারেশনগুলি নির্দিষ্ট ভাষা এবং পরিবেশের জন্য টেইলারিংয়ের অভাবে ব্যবহারের উদ্দেশ্যে হয় " । তুর্কি বিন্দুযুক্ত মূলধন I এবং বিন্দুবিহীন ছোট আমি কেসিংয়ের বিধিগুলি স্পেশাল কেসিং.টেক্সটে রয়েছে। "নন-তুর্কি ভাষার জন্য, এই ম্যাপিংটি সাধারণত ব্যবহৃত হয় না" " ইউনিকোড এফএকিউ থেকে: প্রশ্ন: তুর্কি ভাষার স্থানীয়-স্বাধীন ক্যাসিকে সমর্থন করার জন্য অতিরিক্ত অক্ষরগুলি এনকোড করা হয়নি কেন?
jfs

1
@ জেএফ-সেবাস্তিয়ান আমি এই মামলাফোল্ড () দুর্ব্যবহারের কথা বলিনি। এটা ঠিক ব্যবহারিক যদি এটা একটি ঐচ্ছিক প্যারামিটার যে বড় হাতের বিশেষ চিকিত্সা সক্ষম এবং আই বড়হাতের ডটেড উদাহরণস্বরূপ বাস্তবায়িত হবে, পথ foldCase () আইসিইউ লাইব্রেরিতে এটা আছে : "কেস-ভাঁজ লোকেল স্বাধীন এবং কনটেক্সট হয় সংবেদনশীল, তবে কেসফোল্ডিং.টেক্সট-এ 'টি' দিয়ে চিহ্নিত চিহ্নিত আই এবং ডটলেস আইয়ের জন্য ম্যাপিংগুলি অন্তর্ভুক্ত করা বা বাদ দেওয়ার জন্য বিকল্প রয়েছে "
সের্গি কোলেস্নিকভ

6

আমি রেজিগ্স ব্যবহার করে এই সমাধানটি এখানে দেখেছি ।

import re
if re.search('mandy', 'Mandy Pande', re.IGNORECASE):
# is True

এটি অ্যাকসেন্টগুলির সাথে ভালভাবে কাজ করে

In [42]: if re.search("ê","ê", re.IGNORECASE):
....:        print(1)
....:
1

তবে এটি ইউনিকোড অক্ষর কেস-সংবেদনশীল নিয়ে কাজ করে না। @ রেমোইডকে এই বিষয়টি নির্দেশ করার জন্য আপনাকে ধন্যবাদ জানাই যে আমার বিষয়টি যেমন বোঝাচ্ছিল যে কেসটি সত্য হওয়ার জন্য এটির সঠিক চিহ্ন প্রয়োজন needs আউটপুট নিম্নরূপ:

In [36]: "ß".lower()
Out[36]: 'ß'
In [37]: "ß".upper()
Out[37]: 'SS'
In [38]: "ß".upper().lower()
Out[38]: 'ss'
In [39]: if re.search("ß","ßß", re.IGNORECASE):
....:        print(1)
....:
1
In [40]: if re.search("SS","ßß", re.IGNORECASE):
....:        print(1)
....:
In [41]: if re.search("ß","SS", re.IGNORECASE):
....:        print(1)
....:

4
সত্য যে ßমধ্যে খুঁজে পাওয়া যায় নি SSকেস-অবশ সন্ধানের সাথে প্রমাণ এটা কাজ করে না ইউনিকোড অক্ষর সঙ্গে কাজ সব সময়ে

3

স্বাভাবিক পদ্ধতিটি হ'ল স্ট্রিংগুলি বড় হাতের অক্ষর বা লুকের জন্য তাদের তুলনা করা বা তুলনা করা। উদাহরণ স্বরূপ:

>>> "hello".upper() == "HELLO".upper()
True
>>> 

2

প্রথমে লোয়ারকেসে রূপান্তর সম্পর্কে কীভাবে? আপনি ব্যবহার করতে পারেন string.lower()


4
আপনি তাদের ছোট হাতের মানচিত্র তুলনা করতে পারবেন না: Σίσυφοςএবং ΣΊΣΥΦΟΣসমমানের পরীক্ষা করবেন না, তবে হওয়া উচিত।
14:25 এ tchrist

-2
def insenStringCompare(s1, s2):
    """ Method that takes two strings and returns True or False, based
        on if they are equal, regardless of case."""
    try:
        return s1.lower() == s2.lower()
    except AttributeError:
        print "Please only pass strings into this method."
        print "You passed a %s and %s" % (s1.__class__, s2.__class__)

3
আপনি স্ট্যান্ডআউটে মুদ্রিত বার্তা দ্বারা একটি ব্যতীত প্রতিস্থাপন করছেন, তারপরে কিছুই ফিরিয়ে দিচ্ছেন না, যা মিথ্যা se এটি অনুশীলনে খুব অপ্রয়োজনীয়।
অঙ্কিত

-2

আপনাকে যা করতে হবে তা হ'ল দুটি স্ট্রিংকে ছোট হাতের অক্ষরে রূপান্তর করা (সমস্ত অক্ষর ছোট হাতের অক্ষরে পরিণত হয়) এবং তারপরে তাদের তুলনা করুন (ধরে নিচ্ছেন স্ট্রিংগুলি ASCII স্ট্রিং রয়েছে)।

উদাহরণ স্বরূপ:

string1 = "Hello World"
string2 = "hello WorlD"

if string1.lower() == string2.lower():
    print("The two strings are the same.")
else:
    print("The two strings are not the same."

এই উত্তরটি কোনও নতুন তথ্য যোগ করে না। তদুপরি, এটি গৃহীত উত্তরের মতো প্রায় একই ।
জর্জি

-3

এটি আর একটি রেইজেক্স যা আমি গত সপ্তাহে ভালোবাসতে / ঘৃণা করতে শিখেছি তাই সাধারণত (এই ক্ষেত্রে হ্যাঁ) এমন কিছু আমদানি করে যা প্রতিচ্ছবি অনুভব করে! একটি সাধারণ ফাংশন করুন .... ইনপুট জিজ্ঞাসা করুন, তারপরে ব্যবহার করুন .... কিছু = রেটকমাইল (r'foo * | স্প্যাম * ', হ্যাঁ.আই) ...... পুনরায় (হ্যাঁ.আই) নীচে) IGNORECASE হিসাবে একই তবে আপনি এটি লিখতে যত ভুল করতে পারবেন না!

এরপরে আপনি আপনার বার্তাটি রেগেক্সের ব্যবহার করে অনুসন্ধান করুন তবে সত্যতার সাথে এটি কয়েকটি পৃষ্ঠাতে হওয়া উচিত তবে মূল বিষয়টি হ'ল foo বা স্প্যাম একসাথে পাইপ করা হয় এবং কেস উপেক্ষা করা হয়। তারপরে যদি উভয়ই খুঁজে পাওয়া যায় তবে হারিয়ে যাওয়া_ফোঁটা তাদের মধ্যে একটি প্রদর্শন করবে। যদি না হয় তবে হারানো_ফৌজটি কোনওটির সমান নয়। যদি এটির সমান না হয় তবে "রিটার্ন হারানো_ন_ফাউন্ড। ফ্লায়ার ()"

এটি আপনাকে অনেক সহজেই সংবেদনশীল হতে পারে এমন কোনও কিছুর সাথে মেলে তুলতে দেয়। সবশেষে (এনসিএস) এর অর্থ দাঁড়ায় "কেউ গুরুত্বের সাথে চিন্তা করে না ...!" বা কেস সংবেদনশীল নয় .... যাই হোক না কেন

কারও যদি কোন প্রশ্ন থাকে তবে আমাকে এই সম্পর্কে জিজ্ঞাসা করুন ..

    import re as yes

    def bar_or_spam():

        message = raw_input("\nEnter FoO for BaR or SpaM for EgGs (NCS): ") 

        message_in_coconut = yes.compile(r'foo*|spam*',  yes.I)

        lost_n_found = message_in_coconut.search(message).group()

        if lost_n_found != None:
            return lost_n_found.lower()
        else:
            print ("Make tea not love")
            return

    whatz_for_breakfast = bar_or_spam()

    if whatz_for_breakfast == foo:
        print ("BaR")

    elif whatz_for_breakfast == spam:
        print ("EgGs")
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.