स्विफ्ट स्ट्रिंग्स में इमोजी जैसे पात्र इतने अजीब तरीके से क्यों व्यवहार किए जाते हैं?


539

चरित्र 👩 two👧👧👦👦 (दो महिलाओं, एक लड़की और एक लड़के के साथ परिवार) इस तरह से इनकोड किया गया है:

U+1F469 WOMAN,
‍U+200D ZWJ,
U+1F469 WOMAN,
U+200D ZWJ,
U+1F467 GIRL,
U+200D ZWJ,
U+1F466 BOY

तो यह बहुत दिलचस्प है-एन्कोडेड; एक इकाई परीक्षण के लिए सही लक्ष्य। हालांकि, स्विफ्ट को यह पता नहीं लगता है कि इसका इलाज कैसे किया जाता है। यहाँ मेरा मतलब है:

"👩‍👩‍👧‍👦".contains("👩‍👩‍👧‍👦") // true
"👩‍👩‍👧‍👦".contains("👩") // false
"👩‍👩‍👧‍👦".contains("\u{200D}") // false
"👩‍👩‍👧‍👦".contains("👧") // false
"👩‍👩‍👧‍👦".contains("👦") // true

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

अगर मैं कुछ का उपयोग करता हूं तो यह नहीं बदलता है "👩".characters.first!


इससे भी अधिक उलझन यह है:

let manual = "\u{1F469}\u{200D}\u{1F469}\u{200D}\u{1F467}\u{200D}\u{1F466}"
Array(manual.characters) // ["👩‍", "👩‍", "👧‍", "👦"]

हालाँकि मैंने ZWJ को वहाँ रखा था, वे वर्ण सरणी में परिलक्षित नहीं होते हैं। इसके बाद क्या हुआ थोड़ा बता रहा है:

manual.contains("👩") // false
manual.contains("👧") // false
manual.contains("👦") // true

इसलिए मुझे चरित्र सरणी के साथ एक ही व्यवहार मिलता है ... जो कि बहुत कष्टप्रद है, क्योंकि मुझे पता है कि सरणी कैसा दिखता है।

अगर मैं किसी चीज का उपयोग करता हूं तो यह भी नहीं बदलता है "👩".characters.first!



1
टिप्पणियाँ विस्तारित चर्चा के लिए नहीं हैं; इस वार्तालाप को बातचीत में स्थानांतरित कर दिया गया है ।
मार्टिन पीटर्स

1
स्विफ्ट 4 में फिक्स्ड। "👩‍👩‍👧‍👦".contains("\u{200D}")अभी भी गलत है, यकीन है कि अगर यह एक बग या सुविधा है।
केविन

4
ओह। यूनिकोड ने पाठ को बर्बाद कर दिया है। यह सादे पाठ को मार्कअप भाषा में बदल दिया गया है।
Boann

6
@ हाँ, नहीं और नहीं ... इन परिवर्तनों में से बहुत से हैंगुल जैमो (255 कोडपॉइंट्स) जैसी एन / डीकोडिंग चीजों को बनाने के लिए लगाए गए थे, यह एक पूर्ण दुःस्वप्न नहीं था जैसे कि कांजी (13,108 कोडपॉइंट्स) और चीनी आइडिएट्स (199,528 कोडपॉइंट्स) थे। बेशक, यह एक एसओ टिप्पणी की लंबाई से अधिक जटिल और दिलचस्प है, इसलिए मैं आपको इसे स्वयं जांचने के लिए प्रोत्साहित करता हूं: डी
बेन लेगिएरियो

जवाबों:


401

यह Stringस्विफ्ट कैसे काम करता है, और contains(_:)विधि कैसे काम करती है, इसके साथ क्या करना है ।

The 'known'👧👧👦👦 ’एक इमोजी अनुक्रम के रूप में जाना जाता है, जिसे एक स्ट्रिंग में एक दृश्यमान चरित्र के रूप में प्रस्तुत किया गया है। अनुक्रम Characterवस्तुओं से बना है , और साथ ही यह UnicodeScalarवस्तुओं से बना है ।

यदि आप स्ट्रिंग के कैरेक्टर काउंट की जाँच करते हैं, तो आप देखेंगे कि यह चार अक्षरों से बना है, जबकि यदि आप यूनिकोड स्केलर काउंट की जाँच करते हैं, तो यह आपको एक अलग परिणाम दिखाएगा:

print("👩‍👩‍👧‍👦".characters.count)     // 4
print("👩‍👩‍👧‍👦".unicodeScalars.count) // 7

अब, यदि आप वर्णों के माध्यम से पार्स करते हैं और उन्हें प्रिंट करते हैं, तो आप देखेंगे कि सामान्य पात्रों की तरह क्या लगता है, लेकिन वास्तव में तीन पहले पात्रों में एक इमोजी और साथ ही साथ एक शून्य-चौड़ाई वाले योजक शामिल हैं UnicodeScalarView:

for char in "👩‍👩‍👧‍👦".characters {
    print(char)

    let scalars = String(char).unicodeScalars.map({ String($0.value, radix: 16) })
    print(scalars)
}

// 👩‍
// ["1f469", "200d"]
// 👩‍
// ["1f469", "200d"]
// 👧‍
// ["1f467", "200d"]
// 👦
// ["1f466"]

जैसा कि आप देख सकते हैं, केवल अंतिम वर्ण में शून्य-चौड़ाई वाला योजक शामिल नहीं है, इसलिए contains(_:)विधि का उपयोग करते समय , यह आपकी अपेक्षा के अनुरूप काम करता है। चूंकि आप शून्य-चौड़ाई वाले जॉइनरों वाले इमोजी के खिलाफ तुलना नहीं कर रहे हैं, इसलिए विधि किसी भी अंतिम वर्ण के लिए मैच नहीं ढूंढेगी।

इस पर विस्तार करने के लिए, यदि आप एक Stringऐसा बनाते हैं जो शून्य-चौड़ाई वाले योजक के साथ समाप्त होने वाले इमोजी चरित्र से बना होता है, और इसे contains(_:)विधि में पास करता है , तो यह भी मूल्यांकन करेगा false। इसका contains(_:)ठीक उसी प्रकार से होना है range(of:) != nil, जैसा कि दिए गए तर्क का सटीक मिलान खोजने की कोशिश करता है। चूंकि शून्य-चौड़ाई वाले योजक के साथ समाप्त होने वाले वर्ण एक अपूर्ण अनुक्रम बनाते हैं, इसलिए विधि एक पूर्ण-अनुक्रम में शून्य-चौड़ाई वाले योजक के साथ समाप्त होने वाले वर्णों को मिलाते हुए तर्क के लिए एक मैच खोजने की कोशिश करती है। इसका मतलब है कि विधि कभी भी एक मैच नहीं ढूंढेगी यदि:

  1. तर्क शून्य-चौड़ाई वाले योजक के साथ समाप्त होता है, और
  2. पार्स करने के लिए स्ट्रिंग में एक अधूरा अनुक्रम नहीं होता है (यानी एक शून्य-चौड़ाई वाले योजक के साथ समाप्त होता है और एक संगत चरित्र द्वारा पीछा नहीं किया जाता है)।

प्रदर्शित करना:

let s = "\u{1f469}\u{200d}\u{1f469}\u{200d}\u{1f467}\u{200d}\u{1f466}" // 👩‍👩‍👧‍👦

s.range(of: "\u{1f469}\u{200d}") != nil                            // false
s.range(of: "\u{1f469}\u{200d}\u{1f469}") != nil                   // false

हालाँकि, चूंकि तुलना केवल आगे की है, आप पीछे की ओर काम करके स्ट्रिंग के भीतर कई अन्य पूर्ण अनुक्रम पा सकते हैं:

s.range(of: "\u{1f466}") != nil                                    // true
s.range(of: "\u{1f467}\u{200d}\u{1f466}") != nil                   // true
s.range(of: "\u{1f469}\u{200d}\u{1f467}\u{200d}\u{1f466}") != nil  // true

// Same as the above:
s.contains("\u{1f469}\u{200d}\u{1f467}\u{200d}\u{1f466}")          // true

सबसे आसान समाधान range(of:options:range:locale:)विधि के लिए एक विशिष्ट तुलना विकल्प प्रदान करना होगा । विकल्प String.CompareOptions.literalएक सटीक चरित्र-दर-वर्ण समानता पर तुलना करता है । एक साइड नोट के रूप में, यहां चरित्र का क्या मतलब है , स्विफ्ट नहीं है Character, लेकिन यूटीएफ -16 दोनों उदाहरण और तुलना स्ट्रिंग का प्रतिनिधित्व करते हैं - हालांकि, चूंकि Stringविकृत यूटीएफ -16 अनुमति नहीं देता है, यह अनिवार्य रूप से यूनिकोड स्केलर की तुलना करने के बराबर है। प्रतिनिधित्व।

यहाँ मैंने Foundationविधि को ओवरलोड किया है, इसलिए यदि आपको मूल एक की आवश्यकता है, तो इस एक या कुछ का नाम बदलें:

extension String {
    func contains(_ string: String) -> Bool {
        return self.range(of: string, options: String.CompareOptions.literal) != nil
    }
}

अब यह विधि अधूरे क्रमों के साथ भी प्रत्येक वर्ण के साथ "होनी चाहिए":

s.contains("👩")          // true
s.contains("👩\u{200d}")  // true
s.contains("\u{200d}")    // true

47
@MartinR वर्तमान UTR29 (यूनिकोड 9.0) के अनुसार, यह है एक विस्तारित ग्रफीम क्लस्टर ( GB10 और GB11 नियम ), लेकिन स्पष्ट रूप से स्विफ्ट एक पुराने संस्करण का उपयोग करता है। स्पष्ट रूप से फिक्सिंग जो भाषा के संस्करण 4 के लिए एक लक्ष्य है , इसलिए यह व्यवहार भविष्य में बदल जाएगा।
माइकल होमर

9
@ मिचेलहोमर: स्पष्ट रूप से जो तय किया गया है, वर्तमान एक्सकोड 9 बीटा और स्विफ्ट 4 के साथ "👩‍👩‍👧‍👦".countमूल्यांकन करता है1
मार्टिन आर

5
वाह। यह उत्कृष्ट है। लेकिन अब मैं पुराने दिनों के लिए उदासीन हो रहा हूं, जब मुझे तार के साथ सबसे खराब समस्या यह है कि क्या वे सी या पास्कल शैली के एन्कोडिंग का उपयोग करते हैं।
ओवेन गॉडफ्रे

2
मैं समझता हूं कि यूनिकोड मानक को इसका समर्थन करने की आवश्यकता क्यों हो सकती है, लेकिन यार, यह एक बड़ी गड़बड़ है, अगर कुछ भी: /
मोनिका

109

पहली समस्या यह है कि आप फाउंडेशन के साथ contains(स्विफ्ट की Stringनहीं है Collection) के लिए ब्रिजिंग कर रहे हैं , तो यह NSStringव्यवहार है, जो मुझे विश्वास नहीं है कि स्विफ्ट के रूप में इमोजी के रूप में शक्तिशाली रूप से बनाए गए हैंडल हैं। उस ने कहा, स्विफ्ट मेरा मानना ​​है कि अभी यूनिकोड 8 को लागू किया जा रहा है, जिसे यूनिकोड 10 में इस स्थिति के आसपास भी संशोधन की आवश्यकता है (इसलिए जब वे यूनिकोड 10 को लागू करते हैं तो यह सब बदल सकता है; मैंने इसमें नहीं खोदा है या नहीं)।

बात को सरल बनाने के लिए, आइए फाउंडेशन से छुटकारा पाएं, और स्विफ्ट का उपयोग करें, जो ऐसे विचार प्रदान करता है जो अधिक स्पष्ट हैं। हम पात्रों के साथ शुरू करेंगे:

"👩‍👩‍👧‍👦".characters.forEach { print($0) }
👩‍
👩‍
👧‍
👦

ठीक। यही हमें उम्मीद थी। लेकिन यह झूठ है। आइए देखें कि वे पात्र वास्तव में क्या हैं।

"👩‍👩‍👧‍👦".characters.forEach { print(String($0).unicodeScalars.map{$0}) }
["\u{0001F469}", "\u{200D}"]
["\u{0001F469}", "\u{200D}"]
["\u{0001F467}", "\u{200D}"]
["\u{0001F466}"]

आह… तो यह है ["👩ZWJ", "👩ZWJ", "👧ZWJ", "👦"]। यह सब कुछ थोड़ा और स्पष्ट करता है। (इस सूची का सदस्य नहीं है (यह "WZWJ") है, लेकिन member सदस्य है।

समस्या यह है कि Characterएक "ग्रैपहेम क्लस्टर" है, जो चीजों को एक साथ बनाता है (जैसे जेडडब्ल्यूजे संलग्न करना)। जो आप वास्तव में खोज रहे हैं वह एक यूनिकोड स्केलर है। और यह ठीक उसी तरह काम करता है जैसा आप उम्मीद कर रहे हैं:

"👩‍👩‍👧‍👦".unicodeScalars.contains("👩") // true
"👩‍👩‍👧‍👦".unicodeScalars.contains("\u{200D}") // true
"👩‍👩‍👧‍👦".unicodeScalars.contains("👧") // true
"👩‍👩‍👧‍👦".unicodeScalars.contains("👦") // true

और निश्चित रूप से हम वहां मौजूद वास्तविक चरित्र की तलाश कर सकते हैं:

"👩‍👩‍👧‍👦".characters.contains("👩\u{200D}") // true

(यह बेन लेगिएरो के बिंदुओं पर भारी नक़ल करता है। मैंने इसका उत्तर देने से पहले यह पोस्ट किया था। मामले में छोड़ने से यह किसी के लिए भी स्पष्ट है।)


Wth के ZWJलिए खड़ा है?
लिनसग्राफर्थ

2
शून्य चौड़ाई योजक
रॉब नेपियर

स्विफ्ट 4 में @RobNapier Stringको कथित तौर पर एक संग्रह प्रकार में बदल दिया गया था। क्या यह आपके जवाब को बिल्कुल प्रभावित करता है?
बेन लेगिएरो जू

नहीं। बस सब्स्क्राइब करने जैसी चीजें बदल गईं। यह नहीं बदला कि वर्ण कैसे काम करते हैं।
रोब नेपियर

75

ऐसा लगता है कि स्विफ्ट ZWJएक विस्तारित ग्रैपहेम क्लस्टर को चरित्र के साथ मानता है जो इसे तुरंत पूर्ववर्ती कर रहा है। हम यह देख सकते हैं कि पात्रों के सरणी का मानचित्रण करते समय unicodeScalars:

Array(manual.characters).map { $0.description.unicodeScalars }

यह LLDB से निम्नलिखित प्रिंट करता है:

4 elements
  ▿ 0 : StringUnicodeScalarView("👩‍")
    - 0 : "\u{0001F469}"
    - 1 : "\u{200D}"1 : StringUnicodeScalarView("👩‍")
    - 0 : "\u{0001F469}"
    - 1 : "\u{200D}"2 : StringUnicodeScalarView("👧‍")
    - 0 : "\u{0001F467}"
    - 1 : "\u{200D}"3 : StringUnicodeScalarView("👦")
    - 0 : "\u{0001F466}"

इसके अतिरिक्त, .containsसमूहों ने एक ही वर्ण में अंगूर के समूहों को बढ़ाया। उदाहरण के लिए, हंगुल वर्णों को लेना , और (जो "एक" के लिए कोरियाई शब्द बनाने के लिए गठबंधन करता है:) 한:

"\u{1112}\u{1161}\u{11AB}".contains("\u{1112}") // false

यह नहीं मिल सका क्योंकि तीन कोडपॉइंट एक क्लस्टर में वर्गीकृत किए गए हैं जो एक वर्ण के रूप में कार्य करता है। इसी तरह, \u{1F469}\u{200D}( WOMAN ZWJ) एक क्लस्टर है, जो एक वर्ण के रूप में कार्य करता है।


19

अन्य उत्तर चर्चा करते हैं कि स्विफ्ट क्या करता है, लेकिन इसके बारे में ज्यादा विस्तार में नहीं जाना चाहिए।

क्या आप उम्मीद करते हैं कि “to” की बराबरी “Å” से होगी? मुझे उम्मीद है कि आप करेंगे।

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

अब टेक्स्ट संदेश सेवाएं वर्षों के लिए चित्रमय इमोजी में अक्षरों के संयोजन किया गया है :) →  🙂। इसलिए यूनिकोड में विभिन्न इमोजी जोड़े गए।
इन सेवाओं ने इमोजी को एक साथ मिश्रित इमोजी में जोड़ना शुरू किया।
निश्चित रूप से सभी संभावित संयोजनों को व्यक्तिगत कोडपॉइंट्स में एन्कोड करने का कोई उचित तरीका नहीं है, इसलिए यूनिकोड कंसोर्टियम ने इन समग्र वर्णों को शामिल करने के लिए अंगूर की अवधारणा पर विस्तार करने का निर्णय लिया।

अगर यह उबलता है तो "👩‍👩‍👧‍👦"इसे एक "ग्रैफेम क्लस्टर" के रूप में माना जाना चाहिए, अगर आप इसे ग्रैफेमी स्तर पर काम करने की कोशिश कर रहे हैं, जैसा कि स्विफ्ट डिफ़ॉल्ट रूप से करता है।

यदि आप यह जांचना चाहते हैं कि इसमें उसका "👦"हिस्सा है या नहीं, तो आपको नीचे के स्तर पर जाना चाहिए।


मैं स्विफ्ट सिंटैक्स नहीं जानता, इसलिए यहां कुछ पर्ल 6 है जो यूनिकोड के लिए समान स्तर का समर्थन करता है।
(पर्ल 6 यूनिकोड संस्करण 9 का समर्थन करता है ताकि विसंगतियां हो सकती हैं)

say "\c[family: woman woman girl boy]" eq "👩‍👩‍👧‍👦"; # True

# .contains is a Str method only, in Perl 6
say "👩‍👩‍👧‍👦".contains("👩‍👩‍👧‍👦")    # True
say "👩‍👩‍👧‍👦".contains("👦");        # False
say "👩‍👩‍👧‍👦".contains("\x[200D]");  # False

# comb with no arguments splits a Str into graphemes
my @graphemes = "👩‍👩‍👧‍👦".comb;
say @graphemes.elems;                # 1

एक स्तर नीचे चला गया

# look at it as a list of NFC codepoints
my @components := "👩‍👩‍👧‍👦".NFC;
say @components.elems;                     # 7

say @components.grep("👦".ord).Bool;       # True
say @components.grep("\x[200D]".ord).Bool; # True
say @components.grep(0x200D).Bool;         # True

इस स्तर तक नीचे जाने से हालांकि कुछ चीजें कठिन हो सकती हैं।

my @match = "👩‍👩‍👧‍👦".ords;
my $l = @match.elems;
say @components.rotor( $l => 1-$l ).grep(@match).Bool; # True

मुझे लगता है कि .containsस्विफ्ट में यह आसान है, लेकिन इसका मतलब यह नहीं है कि अन्य चीजें नहीं हैं जो अधिक कठिन हो जाती हैं।

इस स्तर पर काम करना उदाहरण के लिए गलती से एक स्ट्रिंग को संयुक्त चरित्र के बीच में विभाजित करना आसान बनाता है।


आप अनजाने में यह पूछ रहे हैं कि यह उच्च स्तर का प्रतिनिधित्व निचले स्तर के प्रतिनिधित्व की तरह काम क्यों नहीं करता है। जवाब बेशक है, यह नहीं माना जाता है।

यदि आप अपने आप से पूछ रहे हैं " यह इतना जटिल क्यों है ", तो इसका जवाब निश्चित रूप से " मनुष्य " है।


4
आपने मुझे अपनी अंतिम उदाहरण पंक्ति में खो दिया; यहाँ क्या करें rotorऔर grepक्या करें? और क्या है 1-$l?
बेन लेग्गीरो

4
"ग्रेफेम" शब्द कम से कम 50 साल पुराना है। यूनिकोड ने इसे मानक के रूप में पेश किया क्योंकि वे पहले से ही "वर्ण" शब्द का उपयोग करते थे, जिसका अर्थ है कि एक वर्ण के रूप में जो आमतौर पर सोचता है उससे काफी अलग है। मैं पढ़ सकता हूं कि आपने जो लिखा है वह सुसंगत है लेकिन संदेह है कि दूसरों को गलत धारणा मिल सकती है, इसलिए यह (उम्मीद है कि स्पष्ट) टिप्पणी।
-'१

2
@BenLeggiero पहले, rotor। कोड की say (1,2,3,4,5,6).rotor(3)पैदावार ((1 2 3) (4 5 6))। वह सूचियों की एक सूची है, प्रत्येक लंबाई 3say (1,2,3,4,5,6).rotor(3=>-2)पैदावार के अलावा दूसरा सबलिस्ट के 2बजाय 4तीसरे के साथ शुरू होता है 3, और इसी तरह पैदावार ((1 2 3) (2 3 4) (3 4 5) (4 5 6))। यदि @matchइसमें "👩‍👩‍👧‍👦".ordsसम्‍मिलित है तो @ ब्रैड कोड केवल एक सब लिस्‍ट बनाता है, इसलिए =>1-$lबिट अप्रासंगिक (अप्रयुक्त) है। यदि इससे @matchछोटा है तो यह केवल प्रासंगिक है @components
raiph

1
grepप्रत्येक तत्व को उसके इनोकैंट (इस मामले में, उदात्त की सूची में @components) से मिलाने की कोशिश करता है । यह प्रत्येक तत्व को उसके मिलान तर्क (इस मामले में @match) के खिलाफ मैच करने की कोशिश करता है । .Boolतो रिटर्न Trueiff grepकम से कम एक मैच पैदा करता है।
23

18

स्विफ्ट 4.0 अपडेट

स्ट्रिंग को स्विफ्ट 4 अपडेट में बहुत सारे संशोधन मिले, जैसा कि SE-0163 में प्रलेखित है । दो इमोजी का उपयोग दो अलग-अलग संरचनाओं का प्रतिनिधित्व करने वाले इस डेमो के लिए किया जाता है। दोनों को इमोजी के अनुक्रम के साथ जोड़ा गया है।

👍🏽दो इमोजी का संयोजन है, 👍और🏽

👩‍👩‍👧‍👦चार इमोजी का संयोजन है, जिसमें शून्य चौड़ाई जॉइनर जुड़ा हुआ है। प्रारूप है👩‍joiner👩‍joiner👧‍joiner👦

1. मायने रखता है

स्विफ्ट 4.0 में इमोजी को ग्रेपम क्लस्टर के रूप में गिना जाता है। हर एक इमोजी को 1 के रूप में गिना जाता है। countसंपत्ति सीधे स्ट्रिंग के लिए भी उपलब्ध है। तो आप इसे सीधे इस तरह से कॉल कर सकते हैं।

"👍🏽".count  // 1. Not available on swift 3
"👩‍👩‍👧‍👦".count  // 1. Not available on swift 3

एक स्ट्रिंग के चरित्र सरणी को स्विफ्ट 4.0 में ग्रैफेमी क्लस्टर के रूप में भी गिना जाता है, इसलिए दोनों निम्नलिखित कोड 1 प्रिंट करते हैं। ये दो इमोजी इमोजी सीक्वेंस के उदाहरण हैं, जहां कई इमोजी को \u{200d}उनके बीच शून्य चौड़ाई के साथ या बिना संयुक्त किया जाता है। तेजी से 3.0 में, इस तरह के स्ट्रिंग के चरित्र सरणी प्रत्येक इमोजी को अलग करती है और परिणाम में कई तत्वों (इमोजी) के साथ एक सरणी होती है। इस प्रक्रिया में शामिल होने वाले को नजरअंदाज कर दिया जाता है। हालाँकि, स्विफ्ट 4.0 में, चरित्र सरणी सभी इमोजी को एक टुकड़े के रूप में देखती है। ताकि किसी भी इमोजी हमेशा 1 होगा।

"👍🏽".characters.count  // 1. In swift 3, this prints 2
"👩‍👩‍👧‍👦".characters.count  // 1. In swift 3, this prints 4

unicodeScalars स्विफ्ट 4 में अपरिवर्तित रहता है। यह दिए गए स्ट्रिंग में अद्वितीय यूनिकोड वर्ण प्रदान करता है।

"👍🏽".unicodeScalars.count  // 2. Combination of two emoji
"👩‍👩‍👧‍👦".unicodeScalars.count  // 7. Combination of four emoji with joiner between them

2. समाहित है

स्विफ्ट 4.0 में, containsविधि इमोजी में शून्य चौड़ाई योजक को अनदेखा करती है। तो यह चार इमोजी घटकों में से किसी के लिए भी सही है "👩‍👩‍👧‍👦", और यदि आप जॉइनर के लिए जाँच करते हैं तो यह गलत है। हालांकि, स्विफ्ट 3.0 में, जॉइनर को नजरअंदाज नहीं किया जाता है और इसके सामने इमोजी के साथ जोड़ा जाता है। इसलिए जब आप "👩‍👩‍👧‍👦"जांचते हैं कि पहले तीन घटक इमोजी शामिल हैं, तो परिणाम गलत होगा

"👍🏽".contains("👍")       // true
"👍🏽".contains("🏽")        // true
"👩‍👩‍👧‍👦".contains("👩‍👩‍👧‍👦")       // true
"👩‍👩‍👧‍👦".contains("👩")       // true. In swift 3, this prints false
"👩‍👩‍👧‍👦".contains("\u{200D}") // false
"👩‍👩‍👧‍👦".contains("👧")       // true. In swift 3, this prints false
"👩‍👩‍👧‍👦".contains("👦")       // true

0

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

टी एल; डॉ। मैंने इन विशेषताओं पर काम किया है और एक लाइब्रेरी खोली है जिसमें मैं JKEmoji के लिए लेखक हूं जो इमोजीस के साथ तार को जोड़ने में मदद करता है। यह आसान के रूप में के रूप में पार्स करने में आता है:

print("I love these emojis 👩‍👩‍👧‍👦💪🏾🧥👧🏿🌈".emojiCount)

5

ऐसा लगता है कि नियमित रूप से नवीनतम यूनिकोड संस्करण ( हाल ही में 12.0 ) के रूप में सभी मान्यता प्राप्त इमोजीस के एक स्थानीय डेटाबेस को ताज़ा करके और बिटमैप प्रतिनिधित्व को देखते हुए चल रहे ओएस संस्करण में एक मान्य इमोजी के रूप में मान्यता प्राप्त है। एक अपरिचित इमोजी चरित्र।

ध्यान दें

मेरे पुस्तकालय के विज्ञापन के लिए एक पिछला उत्तर स्पष्ट रूप से यह बताए बिना हटा दिया गया कि मैं लेखक हूं। मैं इसे फिर से स्वीकार कर रहा हूं।


2
जब मैं आपकी लाइब्रेरी से प्रभावित हूं, और मैं देखता हूं कि यह आम तौर पर विषय से संबंधित कैसे होता है, तो मैं यह नहीं देखता कि यह कैसे सीधे सवाल से संबंधित है
बेन लेगिएरियो
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.