คุณจะรับสตริงไปยังอาร์เรย์อักขระใน JavaScript ได้อย่างไร


369

คุณจะแปลงสตริงเป็นอาร์เรย์อักขระใน JavaScript ได้อย่างไร

ฉันคิดว่าจะได้สตริงเหมือน"Hello world!"อาร์เรย์
['H','e','l','l','o',' ','w','o','r','l','d','!']

คำตอบ:


492

หมายเหตุ: นี่ไม่ใช่การทำตาม unicode "I💖U".split('')ส่งผลให้มีอาร์เรย์อักขระ 4 ตัว["I", "�", "�", "u"]ซึ่งสามารถนำไปสู่ข้อบกพร่องที่เป็นอันตราย ดูคำตอบด้านล่างสำหรับทางเลือกที่ปลอดภัย

เพียงแค่แยกมันด้วยสตริงว่าง

var output = "Hello world!".split('');
console.log(output);

ดูเอกสารString.prototype.split() MDN


31
สิ่งนี้ไม่คำนึงถึงคู่ตัวแทนแทน ผลในการ"𨭎".split('') ["�", "�"]
hippietrail

59
ดูคำตอบของ @ hakatashi ที่อื่นในกระทู้นี้ หวังว่าทุกคนจะเห็นสิ่งนี้ ... อย่าใช้วิธีนี้มันไม่ใช่ความปลอดภัยของผู้ใช้ทั่วไป
i336_

3
สายไปงานเลี้ยง แต่ทำไมบางคนถึงอยากจะจัดเรียงสตริง? สตริงเป็นอาร์เรย์อยู่แล้วหรือฉันผิด "randomstring".length; //12 "randomstring"[2]; //"n"
Luigi van der Pal

4
@LuigivanderPal สตริงไม่ใช่อาร์เรย์ แต่คล้ายกันมาก อย่างไรก็ตามมันไม่ได้คล้ายกับอาเรย์ของตัวละคร สตริงคล้ายกับอาร์เรย์ของตัวเลข 16 บิตซึ่งบางตัวแทนอักขระและบางอันแทนครึ่งหนึ่งของคู่ตัวแทน ตัวอย่างเช่นstr.lengthไม่ได้บอกจำนวนอักขระในสตริงเนื่องจากอักขระบางตัวใช้พื้นที่มากกว่าอักขระอื่น str.lengthบอกจำนวนตัวเลข 16 บิตให้คุณทราบ
Theodore Norvell

289

ในฐานะที่เป็นhippietrail แสดงให้เห็น , คำตอบของ Mederสามารถทำลายคู่ตัวแทนและตีความผิด“ตัวอักษร”. ตัวอย่างเช่น:

// DO NOT USE THIS!
> '𝟘𝟙𝟚𝟛'.split('')
[ '�', '�', '�', '�', '�', '�', '�', '�' ]

ฉันขอแนะนำให้ใช้หนึ่งในฟีเจอร์ ES2015 ต่อไปนี้เพื่อจัดการลำดับอักขระอย่างถูกต้อง

ไวยากรณ์การแพร่กระจาย ( ตอบแล้วโดยแทรกชื่อผู้ใช้ที่นี่)

> [...'𝟘𝟙𝟚𝟛']
[ '𝟘', '𝟙', '𝟚', '𝟛' ]

Array.from

> Array.from('𝟘𝟙𝟚𝟛')
[ '𝟘', '𝟙', '𝟚', '𝟛' ]

uตั้งค่าสถานะRegExp

> '𝟘𝟙𝟚𝟛'.split(/(?=[\s\S])/u)
[ '𝟘', '𝟙', '𝟚', '𝟛' ]

ใช้/(?=[\s\S])/uแทน/(?=.)/uเพราะไม่ตรงกับการขึ้นบรรทัดใหม่.

หากคุณยังอยู่ในยุค ES5.1 (หรือถ้าเบราว์เซอร์ของคุณไม่จัดการ regex นี้อย่างถูกต้อง - เช่น Edge) คุณสามารถใช้ทางเลือกนี้ (transpiled โดยBabel ):

> '𝟘𝟙𝟚𝟛'.split(/(?=(?:[\0-\uD7FF\uE000-\uFFFF]|[\uD800-\uDBFF][\uDC00-\uDFFF]|[\uD800-\uDBFF](?![\uDC00-\uDFFF])|(?:[^\uD800-\uDBFF]|^)[\uDC00-\uDFFF]))/);
[ '𝟘', '𝟙', '𝟚', '𝟛' ]

โปรดทราบว่า Babel พยายามจัดการตัวแทนเสมือนที่ไม่ตรงกันอย่างถูกต้อง อย่างไรก็ตามสิ่งนี้ดูเหมือนจะไม่ได้ผลสำหรับตัวแทนเสมือนต่ำ

ทดสอบทั้งหมดในเบราว์เซอร์ของคุณ:


คุณสร้างตัวละครเหล่านี้ได้อย่างไร ดูเหมือนว่าอักขระแต่ละตัวมีขนาด 4 ไบต์
user420667

2
@ user420667 ตัวละครมาจากระนาบตัวละครเพิ่มเติม (ในตาราง Unicode) ด้วย codepoints "ใหญ่" ดังนั้นพวกเขาจึงไม่พอดีกับ 16 ไบต์ การเข้ารหัส utf-16 ที่ใช้ใน javascript แสดงอักขระเหล่านี้เป็นคู่ตัวแทน (อักขระพิเศษที่ใช้เป็นคู่เท่านั้นในการสร้างอักขระอื่นจากเครื่องบินเพิ่มเติม) เฉพาะอักขระที่เครื่องบิน charachter หลักเท่านั้นที่แสดงด้วย 16 ไบต์ อักขระพิเศษคู่ Surrugate นั้นมาจากระนาบตัวละครหลักด้วยเช่นกัน
Olga

1
ประสิทธิภาพการทำงานของเทคนิคที่แตกต่างกันการแพร่กระจาย op ดูเหมือนแชมป์ (โครเมี่ยม 58)
Adrien

4
โปรดทราบว่าวิธีการแก้ปัญหานี้แยกอิโมจิบางอย่างเช่น🏳️‍🌈และแยกการรวมเครื่องหมายกำกับจากอักขระ หากคุณต้องการที่จะแยกออกเป็นกระจุกตัวอักษรแทนของตัวละครดูstackoverflow.com/a/45238376
user202729

3
โปรดทราบว่าแม้ว่าจะไม่แตกคู่ตัวแทนที่ยอดเยี่ยมมันไม่ได้เป็นทางออกที่ทั่วไปสำหรับการรักษา "ตัวละคร" (หรือมากกว่าอย่างถูกต้องกราฟ ) ร่วมกัน กราฟสามารถประกอบด้วยหลายจุดรหัส; เช่นชื่อของภาษาเทวนาครีคือ "देवनागरी" ซึ่งจะถูกอ่านโดยเจ้าของภาษาเป็นห้าอักษร แต่จะใช้เวลาแปดจุดรหัสการผลิต ...
TJ Crowder

71

spreadไวยากรณ์

คุณสามารถใช้ไวยากรณ์การแพร่กระจายซึ่งเป็น Array Initializer ที่นำมาใช้ในมาตรฐานECMAScript 2015 (ES6) :

var arr = [...str];

ตัวอย่าง

function a() {
    return arguments;
}

var str = 'Hello World';

var arr1 = [...str],
    arr2 = [...'Hello World'],
    arr3 = new Array(...str),
    arr4 = a(...str);

console.log(arr1, arr2, arr3, arr4);

ผลลัพธ์สามรายการแรกใน:

["H", "e", "l", "l", "o", " ", "W", "o", "r", "l", "d"]

ผลลัพธ์สุดท้ายเข้ามา

{0: "H", 1: "e", 2: "l", 3: "l", 4: "o", 5: " ", 6: "W", 7: "o", 8: "r", 9: "l", 10: "d"}

สนับสนุนเบราว์เซอร์

ตรวจสอบตารางการทำงานร่วมกัน ECMAScript ES6


อ่านเพิ่มเติม

spreadถูกอ้างถึงเป็น " splat" (เช่นในPHPหรือRubyหรือเป็น " scatter" (เช่นในPython )


การสาธิต

ลองก่อนซื้อ


1
หากคุณใช้ตัวดำเนินการสเปรดร่วมกับคอมไพเลอร์ถึง ES5 สิ่งนี้จะไม่ทำงานใน IE คำนึงถึงเรื่องนั้นด้วย ฉันใช้เวลาหลายชั่วโมงกว่าจะรู้ว่าปัญหาคืออะไร
Stef van den Berg


10

นี่เป็นคำถามเก่า แต่ฉันเจอวิธีแก้ไขปัญหาอื่นที่ยังไม่ได้ระบุไว้

คุณสามารถใช้ฟังก์ชัน Object.assign เพื่อรับเอาต์พุตที่ต้องการ:

var output = Object.assign([], "Hello, world!");
console.log(output);
    // [ 'H', 'e', 'l', 'l', 'o', ',', ' ', 'w', 'o', 'r', 'l', 'd', '!' ]

ไม่จำเป็นว่าถูกหรือผิดเพียงแค่ตัวเลือกอื่น

Object.assign ได้รับการอธิบายอย่างดีที่ไซต์ MDN


2
นั่นคือวิธีที่จะไปให้Array.from("Hello, world")ไกล
TJ Crowder

@TJCrowder นั่นเป็นวิธีที่ไกลพอที่จะไปถึงได้[..."Hello, world"]
chharvey

@chharvey - Heh :-)
TJ Crowder

9

มันคือ:

var mystring = 'foobar';
console.log(mystring[0]); // Outputs 'f'
console.log(mystring[3]); // Outputs 'b'

หรือสำหรับเวอร์ชันที่เป็นมิตรกับเบราว์เซอร์รุ่นเก่าให้ใช้:

var mystring = 'foobar';
console.log(mystring.charAt(3)); // Outputs 'b'


4
-1: ไม่ใช่ ทดลองใช้:alert("Hello world!" == ['H','e','l','l','o',' ','w','o','r','l','d'])
R. Martinho Fernandes

4
ขอโทษ ฉันเดาว่าฉันหมายถึงอะไรคือ: "คุณสามารถเข้าถึงตัวละครแต่ละตัวโดยการอ้างอิงดัชนีแบบนี้โดยไม่ต้องสร้างอาร์เรย์ตัวละคร"
dansimau

3
ไม่น่าเชื่อถือข้ามเบราว์เซอร์ที่คุณไม่สามารถ มันเป็นคุณสมบัติ ECMAScript Fifth Edition
bobince

8
mystring.charAt(index)รุ่นข้ามเบราว์เซอร์
psmay

1
+1 สำหรับ - ถึงcharAt()แม้ว่าฉันต้องการใช้ชุดตัวเลือก array-ish ยี้ IE
Zenexer

4

มี (อย่างน้อย) สามสิ่งที่แตกต่างที่คุณอาจคิดว่าเป็น "ตัวละคร" และดังนั้นจึงมีวิธีการที่แตกต่างกันสามประเภทที่คุณอาจต้องการใช้

แบ่งออกเป็นหน่วยรหัส UTF-16

เดิมสตริง JavaScript ถูกประดิษฐ์ขึ้นเป็นลำดับของหน่วยรหัส UTF-16 กลับมาที่จุดในประวัติศาสตร์เมื่อมีความสัมพันธ์แบบหนึ่งต่อหนึ่งระหว่างหน่วยรหัส UTF-16 และจุดโค้ด Unicode .lengthทรัพย์สินของสตริงที่มีขนาดความยาวของมันในหน่วย UTF-16 รหัสและเมื่อคุณทำsomeString[i]คุณจะได้รับฉัน TH UTF-16 someStringรหัสหน่วยของ

ดังนั้นคุณสามารถรับอาร์เรย์ของรหัสหน่วย UTF-16 จากสตริงโดยใช้รูปแบบ C-for-loop พร้อมกับตัวแปร index ...

const yourString = 'Hello, World!';
const charArray = [];
for (let i=0; i<=yourString.length; i++) {
    charArray.push(yourString[i]);
}
console.log(charArray);

นอกจากนี้ยังมีวิธีสั้น ๆ เพื่อให้ได้สิ่งเดียวกันเช่นใช้.split()กับสตริงว่างเป็นตัวคั่น:

const charArray = 'Hello, World!'.split('');
console.log(charArray);

อย่างไรก็ตามหากสตริงของคุณมีจุดรหัสที่ประกอบด้วยหลายหน่วยรหัส UTF-16 สิ่งนี้จะแบ่งออกเป็นหน่วยรหัสแต่ละหน่วยซึ่งอาจไม่ใช่สิ่งที่คุณต้องการ ตัวอย่างเช่นสตริง'𝟘𝟙𝟚𝟛'ประกอบด้วยจุดโค้ดยูนิโคดสี่จุด (รหัสจุด 0x1D7D8 ถึง 0x1D7DB) ซึ่งใน UTF-16 แต่ละหน่วยประกอบด้วยหน่วยรหัส UTF-16 สองชุด หากเราแยกสตริงนั้นโดยใช้วิธีการด้านบนเราจะได้รับชุดโค้ดแปดชุด:

const yourString = '𝟘𝟙𝟚𝟛';
console.log('First code unit:', yourString[0]);
const charArray = yourString.split('');
console.log('charArray:', charArray);

แยกเป็นคะแนนรหัส Unicode

ดังนั้นบางทีเราต้องการแบ่งสตริงของเราเป็น Unicode Code Points แทน! มันเป็นไปได้ตั้งแต่ ECMAScript 2015 ได้เพิ่มแนวคิดของการทำซ้ำให้กับภาษา ตอนนี้สตริงเป็น iterables และเมื่อคุณวนซ้ำ (เช่นfor...ofวนซ้ำ) คุณจะได้รับคะแนนโค้ด Unicode ไม่ใช่หน่วยรหัส UTF-16:

const yourString = '𝟘𝟙𝟚𝟛';
const charArray = [];
for (const char of yourString) {
  charArray.push(char);
}
console.log(charArray);

เราสามารถย่นการใช้นี้ให้สั้นลงArray.fromซึ่งจะวนซ้ำไปเรื่อย ๆ ผ่านการ iterable:

const yourString = '𝟘𝟙𝟚𝟛';
const charArray = Array.from(yourString);
console.log(charArray);

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

  • อักขระที่เน้นเสียงหากมีการใช้สำเนียงนั้นกับจุดรวมรหัส
  • ธง
  • อิโมจิบางอย่าง

เราสามารถเห็นด้านล่างว่าถ้าเราพยายามแปลงสตริงที่มีตัวอักษรดังกล่าวเป็นอาเรย์ผ่านกลไกการทำซ้ำด้านบนตัวละครจะแตกตัวในอาร์เรย์ผลลัพธ์ (ในกรณีที่อักขระใด ๆ ไม่แสดงผลในระบบของคุณyourStringด้านล่างประกอบด้วยตัวอักษรAพร้อมสำเนียงเฉียบพลันตามด้วยธงสหราชอาณาจักรตามด้วยหญิงผิวดำ)

const yourString = 'Á🇬🇧👩🏿';
const charArray = Array.from(yourString);
console.log(charArray);

หากเราต้องการให้แต่ละรายการเหล่านี้เป็นรายการเดียวในอาเรย์สุดท้ายของเราจากนั้นเราต้องการอาเรย์ของแบบกราฟิกไม่ใช่รหัสจุด

แยกเป็นกราฟิค

JavaScript ไม่มีการสนับสนุนในตัวสำหรับสิ่งนี้ - อย่างน้อยยังไม่ ดังนั้นเราจำเป็นต้องมีห้องสมุดที่เข้าใจและนำกฎ Unicode มาใช้สำหรับการรวมจุดรหัสใด ๆ เข้าด้วยกันเป็นกราฟ โชคดีที่มีอยู่: orling ของอักษร-แยก คุณจะต้องการติดตั้งด้วย npm หรือหากคุณไม่ได้ใช้ npm ให้ดาวน์โหลดไฟล์ index.js และแสดงด้วย<script>แท็ก สำหรับตัวอย่างนี้ฉันจะโหลดจาก jsDelivr

อักษร-แยกจะช่วยให้เราGraphemeSplitterเรียนกับสามวิธี: splitGraphemes, และiterateGraphemes countGraphemesตามธรรมชาติเราต้องการsplitGraphemes:

const splitter = new GraphemeSplitter();
const yourString = 'Á🇬🇧👩🏿';
const charArray = splitter.splitGraphemes(yourString);
console.log(charArray);
<script src="https://cdn.jsdelivr.net/npm/grapheme-splitter@1.0.4/index.js"></script>

และเรามี - อาร์เรย์ของสามกราฟซึ่งอาจเป็นสิ่งที่คุณต้องการ


2

คุณสามารถวนซ้ำตามความยาวของสตริงและกดอักขระแต่ละตำแหน่ง :

const str = 'Hello World';

const stringToArray = (text) => {
  var chars = [];
  for (var i = 0; i < text.length; i++) {
    chars.push(text[i]);
  }
  return chars
}

console.log(stringToArray(str))


1
ในขณะที่วิธีการนี้มีความจำเป็นมากกว่าการประกาศเล็กน้อยมันเป็นสิ่งที่มีประสิทธิภาพมากที่สุดในหัวข้อนี้และสมควรได้รับความรักมากขึ้น ข้อ จำกัด อย่างหนึ่งของการดึงอักขระบนสตริงตามตำแหน่งคือเมื่อจัดการกับอักขระที่ผ่านการวางแผนหลายภาษาเบื้องต้นในยูนิโค้ดเช่นอีโมจิ "😃".charAt(0)จะส่งคืนอักขระที่ใช้ไม่ได้
KyleMit

2
@ KyleMit นี่ดูเหมือนจะเป็นจริงสำหรับอินพุตสั้น ๆ เท่านั้น การใช้อินพุตที่นานขึ้นทำให้.split("")ตัวเลือกที่เร็วที่สุดอีกครั้ง
Lux

1
นอกจากนี้ยัง.split("")ดูเหมือนว่าจะได้รับการปรับอย่างหนักใน Firefox ในขณะที่ลูปมีประสิทธิภาพคล้ายกันในการแยกโครเมี่ยมและ Firefox ได้เร็วขึ้นอย่างมีนัยสำคัญใน Firefox สำหรับอินพุตขนาดเล็กและขนาดใหญ่
Lux


0

ความเป็นไปได้อย่างหนึ่งคือถัดไป:

console.log([1, 2, 3].map(e => Math.random().toString(36).slice(2)).join('').split('').map(e => Math.random() > 0.5 ? e.toUpperCase() : e).join(''));

-1

แล้วเรื่องนี้ล่ะ

function stringToArray(string) {
  let length = string.length;
  let array = new Array(length);
  while (length--) {
    array[length] = string[length];
  }
  return array;
}

@ KyleMit ดูเหมือนว่าจะเร็วกว่าสำหรับ i loop + push jsperf.com/string-to-character-array/3
msand

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