จะย้อนกลับสตริงที่มีอิโมจิที่ซับซ้อนได้อย่างไร?


194

อินพุต:

Hello world👩‍🦰👩‍👩‍👦‍👦

ผลลัพธ์ที่ต้องการ:

👩‍👩‍👦‍👦👩‍🦰dlrow olleH

ฉันลองใช้หลายวิธี แต่ไม่มีคำตอบที่ถูกต้อง

สิ่งนี้ล้มเหลว:

const text = 'Hello world👩‍🦰👩‍👩‍👦‍👦';

const reversed = text.split('').reverse().join('');

console.log(reversed);

วิธีนี้ใช้งานได้ แต่แบ่ง👩‍👩‍👦‍👦ออกเป็น 4 อิโมจิที่แตกต่างกัน:

const text = 'Hello world👩‍🦰👩‍👩‍👦‍👦';

const reversed = [...text].reverse().join('');

console.log(reversed);

ฉันยังลองทุกคำตอบในคำถามนี้แต่ไม่มีข้อใดได้ผล

มีวิธีที่จะได้ผลลัพธ์ที่ต้องการหรือไม่?


26
ฉันไม่เห็นปัญหากับวิธีแก้ปัญหาที่สอง ฉันขาดอะไรไป?
Pedro Lima

13
ดังนั้นอิโมจิเหล่านี้จึงเป็นอิโมจิแบบผสมผสานมันค่อนข้างน่าสนใจ ขั้นแรกให้คุณมีอีโมจิหน้าผู้หญิงซึ่งแสดงด้วยตัวละครสองตัวของคุณจากนั้นจะมีอักขระเชื่อมต่อพิเศษซึ่งก็คือ charcode 8205 จากนั้นมีอีก 2 ตัวที่แสดงถึง "ผมสีแดง" และอีก 5 ตัวอักษรด้วยกัน หมายถึง 'ผู้หญิงที่มีผมสีแดง'
TKoL

11
ในการย้อนกลับสตริงอย่างถูกต้องด้วยอิโมจิแบบรวมนั้นค่อนข้างซับซ้อนฉันคิดว่า คุณต้องตรวจสอบว่าอีโมจิแต่ละตัวตามด้วยอักขระรหัส 8205 หรือไม่และหากเป็นเช่นนั้นคุณจะต้องรวมกับอีโมจิก่อนหน้าแทนที่จะถือว่าเป็นตัวละครของตัวเอง
ค่อนข้าง

19
Javascript ทำให้ฉันสับสน เป็นการผสมผสานระหว่างแนวคิดภาษาระดับต่ำและระดับสูงที่แปลกประหลาดที่สุด มันอยู่ในระดับที่เป็นนามธรรมโดยสิ้นเชิงหน่วยความจำ (ไม่มีพอยน์เตอร์การจัดการหน่วยความจำแบบแมนนวล) แต่อยู่ในระดับต่ำเพื่อให้ถือว่าสตริงเป็นจุดรหัสใบ้แทนที่จะเป็นคลัสเตอร์กราฟฟี มันสับสนจริงๆและมันทำให้ฉันไม่รู้ว่าจะคาดหวังอะไรได้บ้างเมื่อทำงานกับสิ่งนี้
Alexander

12
@ อเล็กซานเด-ReinstateMonica มีภาษาใด ๆ ที่ไม่แยกโดยแยกอักษรโดยค่าเริ่มต้น? JS แค่จัดเตรียมสตริงมาตรฐานที่เข้ารหัสใน UTF-16
lights0123

คำตอบ:


94

หากคุณสามารถที่จะใช้_.split()ฟังก์ชั่นให้โดยlodash ตั้งแต่เวอร์ชัน 4.0เป็นต้นไป_.split()สามารถแยกอิโมจิแบบ Unicode ได้

การใช้เนทีฟ.reverse().join('')เพื่อย้อนกลับ "อักขระ" ควรใช้ได้ดีกับอิโมจิที่มีตัวเชื่อมความกว้างเป็นศูนย์

function reverse(txt) { return _.split(txt, '').reverse().join(''); }

const text = 'Hello world👩‍🦰👩‍👩‍👦‍👦';
console.log(reverse(text));
<script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.17.20/lodash.min.js" integrity="sha512-90vH1Z83AJY9DmlWa8WkjkV79yfS2n2Oxhsi2dZbIv0nC4E6m5AbH8Nh156kkM7JePmqD6tcZsfad1ueoaovww==" crossorigin="anonymous"></script>


3
บันทึกการเปลี่ยนแปลงที่คุณกล่าวถึง "v4.9.0 - มั่นใจว่า _.split ใช้งานได้กับอิโมจิ" ฉันคิดว่า 4.0 อาจเร็วเกินไป ความคิดเห็นในโค้ดที่ใช้เพื่อแยกสตริง ( github.com/lodash/lodash/blob/4.17.15/lodash.js#L261 ) อ้างถึง mathiasbynens.be/notes/javascript-unicodeซึ่งมาจากปี 2013 ดูเหมือนว่ามันจะดำเนินต่อไปตั้งแต่นั้นมา แต่มันใช้การถอดรหัส unicode regexes ค่อนข้างยาก ฉันไม่เห็นการทดสอบใด ๆ ใน codebase สำหรับการแยก Unicode ทั้งหมดนี้จะทำให้ฉันระมัดระวังในการใช้มันในการผลิต
Michael Anderson

5
ใช้เวลาค้นหาเพียงเล็กน้อยก็พบว่าสิ่งนี้ล้มเหลวreverse("뎌쉐") (2 กราฟภาษาเกาหลี) ซึ่งให้ "ᅰ셔ᄃ" (3 กราฟ)
Michael Anderson

2
ดูเหมือนว่าจะไม่มีวิธีแก้ปัญหาง่ายๆสำหรับปัญหานี้ ไม่ต้องการนำเข้าไลบรารีเพียงเพื่อแก้ปัญหานี้ แต่เป็นวิธีที่น่าเชื่อถือ / สอดคล้องที่สุดในตอนนี้
Hao Wu

1
รุ่งโรจน์สำหรับการรับการทำงานอย่างถูกต้อง😎การกลับทิศทางการเขียนใน Firefox บนวินโดวส์ 10 ยังคงเป็น glitchy ตาดกระจ้อยร่อย (เด็กจบลงในด้านหลัง), ชนะ lodash เพื่อวินโดวส์ 10 ฉันเดาซึ่งน่าจะเป็นงบประมาณค่อนข้างต่ำ😅
องค์รักษ์

54

ฉันใช้ความคิดของ TKoL ในการใช้\u200dอักขระและใช้เพื่อพยายามสร้างสคริปต์ที่เล็กลง

หมายเหตุ: การแต่งเพลงบางรายการไม่ได้ใช้ตัวเชื่อมความกว้างเป็นศูนย์ดังนั้นมันจะมีปัญหากับตัวละครอื่น ๆ

มันใช้การforวนซ้ำแบบเดิมเพราะเราข้ามการทำซ้ำบางอย่างในกรณีที่เราพบอีโมติคอนรวมกัน ภายในforลูปมีwhileลูปเพื่อตรวจสอบว่ามี\u200dอักขระต่อไปนี้หรือไม่ ตราบใดที่ยังมีอีกหนึ่งตัวเราก็เพิ่มอักขระ 2 ตัวถัดไปด้วยและส่งต่อforลูปด้วยการวนซ้ำ 2 ครั้งดังนั้นอีโมติคอนที่รวมกันจะไม่ย้อนกลับ

เพื่อให้ใช้งานได้อย่างง่ายดายกับสตริงใด ๆ ฉันทำให้มันเป็นฟังก์ชันต้นแบบใหม่บนวัตถุสตริง

String.prototype.reverse = function() {
  let textArray = [...this];
  let reverseString = "";

  for (let i = 0; i < textArray.length; i++) {
    let char = textArray[i];
    while (textArray[i + 1] === '\u200d') {
      char += textArray[i + 1] + textArray[i + 2];
      i = i + 2;
    }
    reverseString = char + reverseString;
  }
  return reverseString;
}

const text = "Hello world👩‍🦰👩‍👩‍👦‍👦";

console.log(text.reverse());

//Fun fact, you can chain them to double reverse :)
//console.log(text.reverse().reverse());


5
ฉันคิดว่าเมื่อคุณลากและเลือกข้อความบนเบราว์เซอร์👩‍👩‍👦‍👦สามารถเลือกได้โดยรวมเท่านั้น เบราว์เซอร์รู้ได้อย่างไรว่าเป็นอักขระเดียว มีวิธีทำในตัวหรือไม่?
Hao Wu

10
@HaoWu นี่คือสิ่งที่เรียกว่า "Unicode Segmentation" บน "Grapheme Clusters" เบราว์เซอร์ของคุณ (ซึ่งอาจใช้เบราว์เซอร์ที่ OS ของคุณมีให้) จะแสดงผลและอนุญาตให้เลือกต่อคลัสเตอร์ grapheme คุณสามารถอ่านข้อมูลจำเพาะได้ที่นี่: unicode.org/reports/tr29/#Grapheme_Cluster_Boundaries
lights0123

7
@HaoWu: "เบราว์เซอร์รู้ได้อย่างไรว่าเป็นอักขระเดียว" - ไม่ใช่ "ตัวละครเดียว" มันหลายตัวละครรวมถึงรูปแบบเดียวคลัสเตอร์อักษรกลายเป็นหนึ่งเดียวสัญลักษณ์
Jörg W Mittag

6
เช่นเดียวกับที่นี่ ; องค์ประกอบทั้งหมดไม่ได้ใช้ตัวเชื่อมความกว้างเป็นศูนย์
Holger

6
สิ่งนี้ไม่ได้ย้อนกลับสิ่งใดอย่างถูกต้อง แต่อักขระที่ประกอบขึ้นด้วย ZWJ โปรดไม่ใช่แค่ที่นี่ แต่ตามกฎทั่วไปให้ใช้ไลบรารีภายนอกที่เขียนโดยคนที่รู้ว่าพวกเขากำลังทำอะไรอยู่แทนที่จะแฮ็กโซลูชันที่ออกแบบมาเฉพาะสำหรับกรณีทดสอบเดียว อักษรรูนและlodashห้องสมุดได้รับการแนะนำในคำตอบอื่น ๆ (ผมไม่สามารถรับรองอย่างใดอย่างหนึ่ง)
benrg

47

การกลับข้อความ Unicode นั้นยุ่งยากด้วยเหตุผลหลายประการ

ขั้นแรกขึ้นอยู่กับภาษาการเขียนโปรแกรมสตริงจะแสดงในรูปแบบต่างๆไม่ว่าจะเป็นรายการไบต์รายการหน่วยรหัส UTF-16 (กว้าง 16 บิตมักเรียกว่า "อักขระ" ใน API) หรือเป็นจุดรหัส ucs4 (กว้าง 4 ไบต์)

ประการที่สอง API ที่แตกต่างกันสะท้อนให้เห็นถึงการเป็นตัวแทนภายในในระดับต่างๆ บางส่วนทำงานกับสิ่งที่เป็นนามธรรมของไบต์บางตัวใช้อักขระ UTF-16 บางตัวใช้จุดโค้ด เมื่อการแทนค่าใช้ไบต์หรืออักขระ UTF-16 มักจะมีส่วนของ API ที่ให้คุณเข้าถึงองค์ประกอบของการแสดงนี้รวมถึงส่วนที่ดำเนินการตรรกะที่จำเป็นเพื่อรับจากไบต์ (ผ่าน UTF-8) หรือ UTF-16 อักขระไปยังจุดรหัสจริง

บ่อยครั้งที่ส่วนต่างๆของ API ที่ใช้ตรรกะนั้นและทำให้คุณสามารถเข้าถึงจุดรหัสนั้นได้ถูกเพิ่มเข้ามาในภายหลังเนื่องจากตอนแรกมี ascii 7 บิตจากนั้นอีกเล็กน้อยต่อมาทุกคนคิดว่า 8 บิตเพียงพอแล้วโดยใช้หน้าโค้ดที่แตกต่างกันและแม้กระทั่ง หลังจากนั้น 16 บิตก็เพียงพอสำหรับ Unicode แนวคิดของจุดรหัสเป็นตัวเลขจำนวนเต็มโดยไม่มีขีด จำกัด บนคงที่ในอดีตถูกเพิ่มเป็นความยาวอักขระทั่วไปที่สี่สำหรับการเข้ารหัสข้อความเชิงตรรกะ

การใช้ API ที่ช่วยให้คุณเข้าถึงจุดรหัสจริงดูเหมือนจะเป็นเช่นนั้น แต่...

ประการที่สามมีจุดรหัสปรับเปลี่ยนจำนวนมากที่ส่งผลต่อจุดรหัสถัดไปหรือจุดรหัสต่อไป เช่นมีตัวปรับเสียงที่เปลี่ยน a ต่อไปนี้เป็นä, e ถึงë, & c หมุนจุดรหัสไปรอบ ๆ และกลายเป็นeäซึ่งทำจากตัวอักษรที่แตกต่างกัน มีการแทนค่าโดยตรงของเช่นäเป็นจุดรหัสของตัวเอง แต่การใช้ตัวปรับเปลี่ยนก็ใช้ได้เช่นกัน

ประการที่สี่ทุกอย่างอยู่ในกระแสคงที่ นอกจากนี้ยังมีตัวปรับแต่งมากมายในอีโมจิดังที่ใช้ในตัวอย่างและมีการเพิ่มตัวปรับแต่งเพิ่มเติมทุกปี ดังนั้นหาก API ให้คุณเข้าถึงข้อมูลว่าจุดโค้ดเป็นตัวปรับแต่งหรือไม่เวอร์ชันของ API จะเป็นตัวกำหนดว่ามันรู้จักตัวแก้ไขใหม่ที่เฉพาะเจาะจง

Unicode มีเคล็ดลับแฮ็กแม้ว่าจะเป็นเรื่องเกี่ยวกับรูปลักษณ์ภายนอกเท่านั้น:

มีการเขียนตัวปรับทิศทาง ในกรณีของตัวอย่างจะใช้ทิศทางการเขียนแบบซ้ายไปขวา เพียงเพิ่มตัวปรับทิศทางการเขียนจากขวาไปซ้ายที่จุดเริ่มต้นของข้อความและขึ้นอยู่กับเวอร์ชันของ API / เบราว์เซอร์มันจะมีลักษณะย้อนกลับอย่างถูกต้อง😎

"\ u202e" เรียกว่าการแทนที่จากขวาไปซ้ายซึ่งเป็นรุ่นที่แข็งแกร่งที่สุดของเครื่องหมายจากขวาไปซ้าย

ดูคำอธิบายนี้โดย w3.org

const text = 'Hello world👩‍🦰👩‍👩‍👦‍👦'
console.log('\u202e' + text)

const text = 'Hello world👩‍🦰👩‍👩‍👦‍👦'
let original = document.getElementById('original')
original.appendChild(document.createTextNode(text))
let result = document.getElementById('result')
result.appendChild(document.createTextNode('\u202e' + text))
body {
  font-family: sans-serif
}
<p id="original"></p>
<p id="result"></p>


8
+1 การใช้ bidi อย่างสร้างสรรค์ (-: การปิดการแทนที่ด้วยตัวอักษร POP DIRECTIONAL FORMATTING จะปลอดภัยกว่า'\u202e' + text + '\u202c'เพื่อหลีกเลี่ยงการส่งผลต่อข้อความต่อไปนี้
Beni Cherniavsky-Paskin

2
ขอบคุณ😎มันค่อนข้างจะเป็นเคล็ดลับ hacky และบทความที่ผมเชื่อมโยงกับการไปเป็นจำนวนมากของรายละเอียดที่อธิบายว่าทำไมมันเป็นวิธีที่ชาญฉลาดในการใช้แอตทริบิวต์ HTML แต่วิธีนี้ผมก็สามารถใช้สตริงสำหรับฉันสับ😂
องค์รักษ์

7
Btw. Firefox ของฉันบนเครื่องนี้ (ชนะ 10) ไม่ถูกต้องทั้งหมดเด็ก ๆ อยู่ข้างหลังผู้ปกครองเมื่อเขียนจากขวาไปซ้ายฉันเดาว่ามันยากที่จะเขียนทิศทางให้ถูกต้องด้วยตัวปรับแต่งกลุ่มอีโมจิที่ซับซ้อนจำนวนมากเหล่านี้ ..
yeoman

2
อีกกรณีหนึ่งที่น่าสนุก: สัญลักษณ์บ่งชี้ภูมิภาคที่ใช้สำหรับอิโมจิธง หากคุณใช้สตริง "🇦🇨" (รหัสสองตัวชี้ U + 1F1E6, U + 1F1E8 ทำให้แฟล็กสำหรับ Ascension Island) และพยายามย้อนกลับอย่างไร้เดียงสาคุณจะได้ "🇨🇦" ซึ่งเป็นธงสำหรับแคนาดา
Adam Rosenfield

2
@yeoman FYI: "อักขระ UTF-16" (ตามที่คุณใช้คำนี้) เรียกอีกอย่างว่า " หน่วยรหัส UTF-16 " "อักขระ" มีแนวโน้มที่จะคลุมเครือของคำศัพท์มากเกินไปเนื่องจากสามารถอ้างถึงสิ่งต่างๆได้มากมาย (แต่ในบริบทของ Unicode มักจะเป็นจุดรหัส)
Inkling

39

ฉันรู้ว่า! ฉันจะใช้ RegExp เกิดอะไรขึ้น? (ตอบทิ้งไว้เป็นแบบฝึกหัดสำหรับผู้อ่าน)

const text = 'Hello world👩‍🦰👩‍👩‍👦‍👦';

const reversed = text.match(/.(\u200d.)*/gu).reverse().join('');

console.log(reversed);


5
คำตอบของคุณฟังดูไม่น่าให้อภัย แต่ฉันเรียกคำตอบนี้ว่าใกล้เคียงกับบัญญัติ แน่นอนว่าดีกว่าคำตอบอื่น ๆ ที่พยายามทำสิ่งเดียวกันด้วยตนเอง การปรับแต่งข้อความตามอักขระคือสิ่งที่ regex ได้รับการออกแบบมาสำหรับและมีความโดดเด่นและ Unicode consortium ได้กำหนดมาตรฐานคุณลักษณะ regex ที่จำเป็นอย่างชัดเจน (ซึ่ง ECMAScript จะนำไปใช้อย่างถูกต้องในกรณีนี้) ที่กล่าวว่าไม่สามารถจัดการกับอักขระที่รวมกันได้ (ซึ่ง IIRC regex ควรจัดการด้วย.สัญลักษณ์แทน)
Konrad Rudolph

14
ไม่ได้ทำงานกับองค์ประกอบไม่ได้สร้างขึ้นด้วยเช่นU+200D 🏳️‍🌈เป็นที่น่าสังเกตว่าตัวละครที่แต่งขึ้นเองก็มีอยู่นอกโลก Emijoi เช่นกัน…
Holger

2
@StevenPenny U+200D🏳️🌈มีสององค์ประกอบและหนึ่งในนั้นไม่ได้ใช้ ง่ายต่อการตรวจสอบว่า 🏳️‍🌈 ใช้ไม่ได้กับรหัสของคำตอบนี้…
Holger

1
@Holger ในขณะที่มันเป็นความจริงที่ว่า 🏳️‍🌈 มีองค์ประกอบที่ไม่ได้สร้างด้วย U + 200D มันเป็นตัวอย่างที่ไม่ดีเลยเพราะมันมีองค์ประกอบด้วย U + 200D ด้วย ตัวอย่างที่ดีกว่าก็เช่น🧑🏻หรือ🏳️
Steven Penny

3
ตรงกันข้ามกับความคิดเห็นอื่น ๆ ที่นี่การใช้ตัวเชื่อมศูนย์ความกว้างไม่ควรถือว่าเป็นคลัสเตอร์กราฟฟิมเดียว ตัวอย่างเช่นสามบรรทัดสุดท้ายของการทดสอบ grapheme unicode 13 ( unicode.org/Public/13.0.0/ucd/auxiliary/GraphemeBreakTest.txt ) แสดงกรณีที่คล้ายกันมากสามกรณีที่ ZWJ ได้รับการจัดการแตกต่างกัน
Michael Anderson

32

ทางเลือกอื่นคือการใช้runesไลบรารีโซลูชันขนาดเล็ก แต่มีประสิทธิภาพ:

https://github.com/dotcypress/runes

const runes = require('runes')

// String.substring
'👨‍👨‍👧‍👧a'.substring(1) => '�‍👨‍👧‍👧a'

// Runes
runes.substr('👨‍👨‍👧‍👧a', 1) => 'a'

runes('12👩‍👩‍👦‍👦3🍕✓').reverse().join(); 
// results in: "✓🍕3👩‍👩‍👦‍👦21"

3
นี่คือคำตอบที่ดีที่สุด tbh คำตอบอื่น ๆ ทั้งหมดนี้มีบางกรณีที่ล้มเหลวไลบรารีนี้ (หวังว่า) จะตรงตามขอบข่ายทั้งหมด
Carson Graham

1
เป็นเรื่องตลกที่ "คำถามง่ายๆ" เช่นนี้ในตอนแรกดูจะไม่ใช่เรื่องง่ายที่จะแก้ปัญหา เห็นด้วยกับ Carson - ห้องสมุดหวังว่าจะก้าวไปข้างหน้าด้วยการอัปเดตและการเปลี่ยนแปลงเนื่องจาก Emojis พัฒนาไปเรื่อย ๆ
Arnis Juraga

3
ดูเหมือนว่าสิ่งนี้จะไม่ได้รับการอัปเดตมาประมาณ 3 ปีแล้ว Unicode 11 ได้รับการเผยแพร่ในช่วงเวลานั้น แต่สิ่งต่าง ๆ ได้เปลี่ยนไปตั้งแต่นั้นมาโดย Unicode 13 จะออกในภายหลัง มีการเปลี่ยนแปลงบางอย่างในกฎกราฟฟิมแบบขยายใน 13 ดังนั้นจึงอาจมีกรณีขอบบางอย่างที่ไม่สามารถจัดการได้ (ฉันไม่ได้ดูรหัส - แต่ก็ควรระวังด้วย)
Michael Anderson

2
ฉันเห็นด้วยกับ @MichaelAnderson ห้องสมุดนี้ดูเหมือนจะใช้อัลกอริทึมไร้เดียงสาหรือแบบเก่า การทำเช่นนี้ได้อย่างถูกต้องก็ควรใช้ขั้นตอนวิธีการแบ่งส่วนอักษรที่ระบุไว้ใน Unicode
Inkling

21

คุณไม่เพียงมีปัญหากับอีโมจิ แต่ยังรวมถึงตัวละครอื่น ๆ สิ่งเหล่านี้ที่ให้ความรู้สึกเหมือนตัวอักษรแต่ละตัว แต่จริงๆแล้วเป็นอักขระ Unicode หนึ่งตัวหรือมากกว่านั้นเรียกว่า "คลัสเตอร์ grapheme แบบขยาย"

การแบ่งสตริงออกเป็นคลัสเตอร์เหล่านี้เป็นเรื่องยุ่งยาก (ตัวอย่างเช่นดูเอกสาร Unicodeเหล่านี้) ฉันจะไม่พึ่งพาการใช้งานด้วยตนเอง แต่ใช้ไลบรารีที่มีอยู่ Google ชี้ให้ฉันไปที่ไลบรารีตัวแยกกราฟฟีม เอกสารสำหรับไลบรารีนี้มีตัวอย่างที่ดีที่จะนำไปใช้งานส่วนใหญ่:

เมื่อใช้สิ่งนี้คุณควรจะสามารถเขียน:

var splitter = new GraphemeSplitter();
var graphemes = splitter.splitGraphemes(string);
var reversed = graphemes.reverse().join('');

ASIDE: สำหรับผู้มาเยือนจากอนาคตหรือผู้ที่ต้องการอาศัยอยู่บนขอบเลือด:

มีข้อเสนอคือในการเพิ่ม grapheme segmenter ในมาตรฐานจาวาสคริปต์ (จริงๆแล้วมันมีตัวเลือกการแบ่งกลุ่มอื่น ๆ ด้วย) อยู่ระหว่างการตรวจสอบขั้นตอนที่ 3 สำหรับการยอมรับในขณะนี้และปัจจุบันมีการใช้งานใน JSC และ V8 (ดูhttps://github.com/tc39/proposal-intl-segmenter/issues/114 )

การใช้รหัสนี้จะมีลักษณะดังนี้:

var segmenter = new Intl.Segmenter("en", {granularity: "grapheme"})
var segment_iterator = segmenter.segment(string)
var graphemes = []
for (let {segment} of segment_iterator) {
    graphemes.push(segment)
}
var reversed = graphemes.reverse().join('');

คุณอาจจะทำให้มันดูดีกว่านี้ได้ถ้าคุณรู้จักจาวาสคริปต์ที่ทันสมัยกว่าฉัน ...

มีการนำไปใช้ที่นี่ - แต่ฉันไม่รู้ว่าต้องใช้อะไรบ้าง

หมายเหตุ: สิ่งนี้ชี้ให้เห็นถึงปัญหาสนุก ๆ ที่คำตอบอื่น ๆ ยังไม่ได้กล่าวถึง การแบ่งกลุ่มอาจขึ้นอยู่กับโลแคลที่คุณใช้ไม่ใช่แค่อักขระในสตริง


1
ดูเหมือนว่าโค้ดจะไม่ได้รับการอัปเดตเป็นเวลาประมาณ 2 ปีดังนั้นตารางอาจไม่เป็นปัจจุบัน ดังนั้นคุณอาจต้องค้นหาสิ่งที่ใหม่กว่า
Michael Anderson

3
ดูเหมือนทางแยกล่าสุดของห้องสมุดนี้มีอยู่ที่github.com/flmnt/graphemer
Michael Anderson

4
ฉันแปลกใจที่ต้องเลื่อนลงมาจนสุดเพื่อดูคำตอบที่ถูกต้องจริงๆ
Lambda Fairy

1
const graphemes = Array.from(segment_iterator, ({segment}) => segment)ยกตัวอย่างเช่นข้อเสนอที่คุณสามารถทำได้
Inkling

17

ฉันแค่ตัดสินใจที่จะทำเพื่อความสนุกเป็นความท้าทายที่ดี ไม่แน่ใจว่าถูกต้องในทุกกรณีดังนั้นให้ใช้โดยยอมรับความเสี่ยงเอง แต่นี่คือ:

function run() {
    const text = 'Hello world👩‍🦰👩‍👩‍👦‍👦';
    const newText = reverseText(text);
    console.log(newText);
}

function reverseText(text) {
    // first, create an array of characters
    let textArray = [...text];
    let lastCharConnector = false;
    textArray = textArray.reduce((acc, char, index) => {
        if (char.charCodeAt(0) === 8205) {
            const lastChar = acc[acc.length-1];
            if (Array.isArray(lastChar)) {
                lastChar.push(char);
            } else {
                acc[acc.length-1] = [lastChar, char];
            }
            lastCharConnector = true;
        } else if (lastCharConnector) {
            acc[acc.length-1].push(char);
            lastCharConnector = false;
        } else {
            acc.push(char);
            lastCharConnector = false;
        }
        return acc;
    }, []);
    
    console.log('initial text array', textArray);
    textArray = textArray.reverse();
    console.log('reversed text array', textArray);

    textArray = textArray.map((item) => {
        if (Array.isArray(item)) {
            return item.join('');
        } else {
            return item;
        }
    });

    return textArray.join('');
}

run();


1
ที่จริงมันยาวเพราะข้อมูลการดีบัก ฉันซาบซึ้งจริงๆ
Hao Wu

1
@AndrewSavinykh ไม่ใช่โค้ดกอล์ฟ แต่กำลังมองหาทางออกที่หรูหรากว่านี้ อาจจะไม่เหมือนคนบ้าซับเดียว แต่จำง่าย เช่นโซลูชัน regexเป็น imho ที่ดีมาก
Hao Wu

0

คุณสามารถใช้ได้:

yourstring.split('').reverse().join('')

ควรเปลี่ยนสตริงของคุณให้เป็นรายการย้อนกลับแล้วทำให้เป็นสตริงอีกครั้ง


3
คุณอ่านคำถามแล้วหรือยัง? รหัสของคุณเป็นรหัส OP ที่พิสูจน์แล้วว่าผิดในคำถาม
Washington Guedes

-1

const text = 'สวัสดีชาวโลก ‍🦰👩‍👩‍👦‍👦';

const กลับด้าน = text.split (''). reverse (). join ('');

console.log (ย้อนกลับ);

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.