Як я можу обробити кожну букву тексту за допомогою Javascript?


361

Я хотів би попередити кожну окрему букву рядка, але я не знаю, як це зробити.

Отже, якщо у мене є:

var str = 'This is my string';

Я хотів би мати можливість окремо попередити T, h, i, s тощо. Це лише початок ідеї, над якою я працюю, але мені потрібно знати, як опрацювати кожен лист окремо.

Я хочу використовувати jQuery і думав, що, можливо, мені потрібно буде використовувати функцію розділення після тестування, яка довжина рядка.

Ідеї?


3
Можливо, ви шукали це: як на ES6, там є for(const c of str) { ... }. Більше про це далі в досить детальній, але недостатньо обґрунтованій відповіді. PS: @ ARJUN посилання для мене не працює.
Макс

Відповіді:


419

Якщо порядок оповіщення має значення, скористайтеся цим:

for (var i = 0; i < str.length; i++) {
  alert(str.charAt(i));
}

Якщо порядок оповіщення не має значення, скористайтеся цим:

var i = str.length;
while (i--) {
  alert(str.charAt(i));
}


2

13
як описано в іншій відповіді, ви можете використовувати str.charAt (i) замість [] 's. Докладніше про те, чому слід використовувати charAt vs [], див. string.charAt (x) або string [x]
Julian Soro

12
Мені важко повірити, що будь-який сучасний компілятор JS перерахував би довжину, якщо рядок не змінено всередині циклу. На будь-якій іншій мові я б із задоволенням перевіряв довжину в тестовому пункті циклу for, припускаючи, що компілятор знає найкраще і оптимізував би його відповідно.
Ешелон

3
@Dagmar: Javascript не використовує UTF-8, він використовує UTF-16 (або UCS-2, залежно від браузера). Кожен окремий символ може бути представлений як UTF-8 або UTF-16, але не має цієї проблеми. Єдині проблеми, які потребують чотирьох байт у UTF-16, а не два байти. 💩 - символ, який вимагає чотирьох байт в UTF-16. Ключові терміни для пошуку додаткової інформації - "астральна площина", "не-BMP" і "сурогатна пара".
hippietrail

1
@Dagmar: І Java, і Javascript мають спільне значення UTF-16 (раніше UCS-). Третя основна платформа, яка ним користується, - Windows. Протоколи Unix, MacOS та Internet використовують UTF-8. charAtзалишилося від UCS-2 днів, коли не було сурогатних пар, і для вирішення проблеми нова функція codepointAtбула додана в JavaScript, який правильно обробляє нашу дружню купу поо. Я вірю, що в Java також є.
hippietrail

240

Це, мабуть, більше, ніж вирішено. Просто хочу внести свій внесок у ще одне просте рішення:

var text = 'uololooo';

// With ES6
[...text].forEach(c => console.log(c))

// With the `of` operator
for (const c of text) {
    console.log(c)
}

// With ES5
for (var x = 0, c=''; c = text.charAt(x); x++) { 
    console.log(c); 
}

// ES5 without the for loop:
text.split('').forEach(function(c) {
    console.log(c);
});

4
останній приклад може бути просто[...text].forEach(console.log)
Говінд Рай

10
Ні, не може. forEach()передає індекс і масив як другий і третій аргумент. Я вважаю за краще це не робити.
Пан Гоферіто,

1
Зауважте, що і оператор розповсюдження (перший приклад), і розділений виклик (останній приклад) створять новий масив. Зазвичай це не буде проблемою, але це може бути дорогим для великих рядків або частого використання.
Рандольфо

Що проfor (let c of [...text]) { console.log(c) }
Flimm

З цим ви створюєте новий масив з рядка. Я не бачу вигоди. let c of textвже виконує роботу.
Містер Гоферіто

73

Одне можливе рішення в чистому javascript:

for (var x = 0; x < str.length; x++)
{
    var c = str.charAt(x);
    alert(c);
}

Напевно, було б краще з var x = 0 і var c = str.charAt (x).
Багатий

2
Крім того, str.length слід зберігати у змінній, щоб не потребувати доступу до нього.
Елі Грей

8
@EliGrey Чи дійсно так важливо ставити довжину в змінну? Чи є у вас орієнтири, коли це було б краще, ніж менше рядків коду?
pm_labs

@paul_sns Цікаво, що, здається, є незначна різниця, принаймні, у Edge (різниця 0,7 мс для масиву елементів 10000): jsfiddle.net/carcigenicate/v8vvjoc1/1 . Можливо, це не ідеальний тест, але він базується на середньому 10000 тестах.
Carcigenicate

1
@paul_sns Також цікаво, що Chrome робив той самий тест приблизно за 2% часу (~ 5 мс проти ~ 0,0977 мс), і обидві версії давали однаковий час, тому схоже, що Edge не оптимізований.
Carcigenicate

69

Як обробити кожну букву тексту (з орієнтирами)

https://jsperf.com/str-for-in-of-foreach-map-2

для

Класичний і, безумовно, той, що має найбільшу продуктивність . Вам слід скористатися цим, якщо ви плануєте використовувати його в алгоритмі критичної продуктивності, або якщо він вимагає максимальної сумісності з версіями браузера.

for (var i = 0; i < str.length; i++) {
  console.info(str[i]);
}

за ... оф

для ... of - це новий ES6 для ітератора. Підтримується більшістю сучасних браузерів. Він візуально привабливіший і менш схильний до помилок введення тексту. Якщо ви збираєтеся це в виробничій програмі, вам, мабуть, слід скористатися транспілятором, як Babel .

let result = '';
for (let letter of str) {
  result += letter;
}

для кожного

Функціональний підхід. Airbnb затверджено . Найбільший недолік зробити це таким чином - це те split(), що створює новий масив для зберігання кожної окремої літери рядка.

Чому? Це виконує наше незмінне правило. Розібратися з чистими функціями, які повертають значення, простіше пояснити, ніж побічні ефекти.

// ES6 version.
let result = '';
str.split('').forEach(letter => {
  result += letter;
});

або

var result = '';
str.split('').forEach(function(letter) {
  result += letter;
});

Нижче перелічені ті, які мені не подобаються.

за ... в

На відміну від ... of, ви отримуєте буквений індекс замість букви. Виступає досить погано.

var result = '';
for (var letterIndex in str) {
  result += str[letterIndex];
}

карта

Функціональний підхід, що добре. Однак карта не призначена для цього для використання. Його слід використовувати, коли потрібно змінювати значення всередині масиву, що не так.

// ES6 version.
var result = '';
str.split('').map(letter => {
  result += letter;
});

або

let result = '';
str.split('').map(function(letter) {
  result += letter;
});

1
На моїй машині класичний forцикл був насправді другим найповільнішим, в той час як for...ofбув найшвидшим (приблизно втричі швидшим for).
Джон Монтгомері

1
Де орієнтир? Що найшвидше рішення?
poitroae

1
@johnywhy Це було два роки тому, і посилання мертва, тому я не впевнений, як ти очікуєш від мене захищати результат, який я отримав тоді. Встановлення нового еталону тепер погоджується із висновком zurfyx, але forцикл трохи швидший.
Джон Монтгомері

1
@JohnMontgomery Я не очікую, що ти щось зробиш. Просто зауваження майбутнім читачам, що ваші результати відрізняються від відповіді. Я особисто хотів би знати, які результати застосовуються до браузерів сьогодні 2020 року, але '2018 рік був не таким уже давно. Яке посилання є мертвим?
Джоні чому

1
@johnywhy Посилання вгорі з усіма актуальними тестами для мене повертає 404.
Джон Монтгомері

42

Більшість, якщо не всі відповіді тут неправильні, тому що вони будуть ламатися, коли в рядку є символ, що знаходиться за межами BMP Unicode (Basic Multilingual Plane) . Це означає, що всі Емоджі будуть зламані .

JavaScript використовує UTF- 16 Unicode для всіх рядків. У UTF-16 символи поза BMP складаються з двох частин, які називаються " сурогатною парою ", і більшість відповідей тут оброблятиме кожну частину таких пар окремо, а не як один символ.

Один із способів у сучасному JavaScript, щонайменше, з 2016 року - використовувати новий ітератор String . Ось приклад (майже) прямо з MDN:

var string = 'A\uD835\uDC68B\uD835\uDC69C\uD835\uDC6A';

for (var v of string) {
  alert(v);
}
// "A"
// "\uD835\uDC68"
// "B"
// "\uD835\uDC69"
// "C"
// "\uD835\uDC6A"


4
Для сучасного рішення розщеплення рядки в символи, беручи до уваги пару сурогатних см: stackoverflow.com/a/42596897/527702
hippietrail

20

Ви можете спробувати це

var arrValues = 'This is my string'.split('');
// Loop over each value in the array.
$.each(arrValues, function (intIndex, objValue) {
    alert(objValue);
})

11
Ще варіант, але не виконавець. Не ставте jQuery скрізь.
cagatay

10

Ще одне рішення ...

var strg= 'This is my string';
for(indx in strg){
  alert(strg[indx]);
}

3
Якщо ви хочете лише знака, а не індексу, скоріше скористатися for..ofцикломfor (let ch of t) { alert(ch) }
Shaheen Ghiassy

10

Коли мені потрібно написати короткий код або однолінійку, я використовую цей "хак":

'Hello World'.replace(/./g, function (char) {
    alert(char);
    return char; // this is optional 
});

Це не буде рахувати нові рядки, так що це може бути хорошою справою чи поганою справою. Якщо ви включаєте нові рядки, замініть: /./на /[\S\s]/. Інший, який ви можете побачити, мабуть, використовує, .split()який має багато проблем


найкраща відповідь.
Враховує

Єдине, що мені не подобається в цьому, це те, коли я хочу отримати доступ до додаткових парам, переданих у функцію forEachвиклику, та над відправленими парамамиreplace . Якщо я знаю, що я ASCIIing, я думаю, що в мене все ще є деякі випадки використання split. Хоча чудова відповідь!
ruffin

У цій відповіді є бонус за попередній вибір значень, які ви все одно перевірите
Fuzzyma

1
Я думав, що це не буде враховувати проблеми Unicode, якщо у нього не буде uпрапор разом із gпрапором? Добре тестував, і я мав рацію.
hippietrail


8

Краще використовувати оператор for ... for, якщо рядок містить символи unicode через різний розмір байтів.

for(var c of "tree 木") { console.log(c); }
//"𝐀A".length === 3

7

коротка відповідь: Array.from(string)дасть вам те, що ви, мабуть, хочете, і тоді ви зможете повторити його чи будь-що інше, оскільки це просто масив.

добре давайте спробуємо з цим рядком: abc|⚫️\n⚪️|👨‍👩‍👧‍👧.

Точки коду:

97
98
99
124
9899, 65039
10
9898, 65039
124
128104, 8205, 128105, 8205, 128103, 8205, 128103

тому деякі символи мають одну кодову точку (байт), а деякі - дві або більше, а для додаткового тестування додається новий рядок.

тож після тестування є два способи:

  • байт на байт (кодова точка на кодову точку)
  • групи персонажів (але не всі сім'ї смайликів)

string = "abc|⚫️\n⚪️|👨‍👩‍👧‍👧"

console.log({ 'string': string }) // abc|⚫️\n⚪️|👨‍👩‍👧‍👧
console.log({ 'string.length': string.length }) // 21

for (let i = 0; i < string.length; i += 1) {
  console.log({ 'string[i]': string[i] }) // byte per byte
  console.log({ 'string.charAt(i)': string.charAt(i) }) // byte per byte
}

for (let char of string) {
  console.log({ 'for char of string': char }) // character groups
}

for (let char in string) {
  console.log({ 'for char in string': char }) // index of byte per byte
}

string.replace(/./g, (char) => {
  console.log({ 'string.replace(/./g, ...)': char }) // byte per byte
});

string.replace(/[\S\s]/g, (char) => {
  console.log({ 'string.replace(/[\S\s]/g, ...)': char }) // byte per byte
});

[...string].forEach((char) => {
  console.log({ "[...string].forEach": char }) // character groups
})

string.split('').forEach((char) => {
  console.log({ "string.split('').forEach": char }) // byte per byte
})

Array.from(string).forEach((char) => {
  console.log({ "Array.from(string).forEach": char }) // character groups
})

Array.prototype.map.call(string, (char) => {
  console.log({ "Array.prototype.map.call(string, ...)": char }) // byte per byte
})

var regexp = /(?:[\0-\uD7FF\uE000-\uFFFF]|[\uD800-\uDBFF][\uDC00-\uDFFF]|[\uD800-\uDBFF](?![\uDC00-\uDFFF])|(?:[^\uD800-\uDBFF]|^)[\uDC00-\uDFFF])/g

string.replace(regexp, (char) => {
  console.log({ 'str.replace(regexp, ...)': char }) // character groups
});


7

Тепер ви можете переглядати окремі точки коду Unicode, що містяться в String, використовуючи String.prototype[@@iterator], що повертає значення добре відомого типу Symbol Symbol.iterator- ітератора за замовчуванням для об’єктів, схожих на масив ( Stringу цьому випадку).

Приклад коду:

const str = 'The quick red 🦊 jumped over the lazy 🐶! 太棒了!';

let iterator = str[Symbol.iterator]();
let theChar = iterator.next();

while(!theChar.done) {
  console.log(theChar.value);
  theChar = iterator.next();
}

// logs every unicode character as expected into the console.

Це працює з символами Unicode, такими як смайли або нероманські символи, які могли б збільшити застарілі конструкти

Довідка: посилання MDN на String.prototype @@ iterator .


2
Зауважте, що це можна зробити коротшим способом і за допомогою for ... ofциклу над рядком - це синтаксичний цукор для доступу до ітератора.
Депутат Адітія

6

Тепер ви можете використовувати в ключових словах.

    var s = 'Alien';
    for (var c in s) alert(s[c]);


Використовувати це є поганою практикою і жахливо, коли нефільтрується, я настійно раджу проти цього
Пуховик

4
@Downgoat чому? Що в цьому поганого? Я маю на увазі, якщо я знаходжусь у ситуації, коли я знаю, що 'in' підтримується моїм механізмом Javascript, і що мій код не знайде свій шлях до іншого двигуна ... чому б не використати це?
TKoL

@TKoL Дивіться це .
Алан

@Alan inє законною частиною мови. Використовуйте речі належним чином. У вашій статті застережено, що inінтерпретовані альфа-клавіші аналогічні цифровим клавішам. Тому? Можливо, саме цього ви хочете. Можна також сказати, що інші методи неправильно ігнорують альфа-клавіші. Імо, ofмає правильну поведінку. У масивах JS елементи без альфа-клавіш все ще мають ключі: числові. У моїй консолі JS "правильно" трактує клавішу альфа так само, як цифрові клавіші:>const arr = ['a', 'b'] >arr.test = 'hello' >arr 0: "a" 1: "b" test: "hello" length: 2
johny чому

5

Ви можете отримати масив окремих символів, як це

var test = "test string",
    characters = test.split('');

а потім циклічно використовуючи звичайний Javascript, інакше ви можете перебирати символи рядка за допомогою jQuery by

var test = "test string";

$(test.split('')).each(function (index,character) {
    alert(character);
});

5

ви можете перетворити цей рядок у масив символів за допомогою split(), а потім повторити його.

const str = "javascript";
const strArray = str.split('');

strArray.map(s => console.log(s));


мабуть, це не вдається з символами unicode та графічними символами.
Джоні чому

4

Якщо ви хочете зробити перетворення тексту на рівні символів і повернути трансформований текст наприкінці, ви зробите щось подібне:

var value = "alma";
var new_value = value.split("").map(function(x) { return x+"E" }).join("")

Отже, кроки:

  • Розбийте рядок на масив (список) символів
  • Мапа кожного символу за допомогою функтора
  • Об’єднайте отриманий масив символів разом у отриманий рядок

0

У сьогоднішньому JavaScript ви можете

Array.prototype.map.call('This is my string', (c) => c+c)

Очевидно, що c + c являє собою все, що ви хочете зробити з c.

Це повертається

["TT", "hh", "ii", "ss", " ", "ii", "ss", " ", "mm", "yy", " ", "ss", "tt", "rr", "ii", "nn", "gg"]


Можливо:[...'This is my string'].map((c)=>c+c)
Алан

0

Це має працювати в старих браузерах і з символами UTF-16, як 💩.

Це має бути найбільш сумісним рішенням. Однак він менш ефективний, ніж forпетля.

Я генерував регулярний вираз за допомогою regexpu

var str = 'My String 💩 ';
var regEx = /(?:[\0-\uD7FF\uE000-\uFFFF]|[\uD800-\uDBFF][\uDC00-\uDFFF]|[\uD800-\uDBFF](?![\uDC00-\uDFFF])|(?:[^\uD800-\uDBFF]|^)[\uDC00-\uDFFF])/g


str.replace(regEx, function (char) {
    console.log(char)
});

Сподіваюся, це допомагає!


Що ви маєте на увазі під "менш популярними"? Я думаю, ви маєте на увазі "повільніше", оскільки він більше відповідає вимогам і він справляється добре.
гіпюр-рейл

-1

Ви можете отримати доступ до окремих символів за допомогою str.charAt(index)або str[index]. Але останній спосіб не є частиною ECMAScript, тому вам краще піти з попереднім.


Я б тримався осторонь цього. На жаль, це працює не у всіх версіях IE. Довірся мені. Я навчився цього важким шляхом.
Хаві

3
Він є частиною ECMAScript, але лише у щойно випущеному 5-му виданні, а не в 3-му.
кенгакс

-1

Якщо ви хочете анімувати кожного персонажа, можливо, вам доведеться загорнути його в елемент span;

var $demoText = $("#demo-text");
$demoText.html( $demoText.html().replace(/./g, "<span>$&amp;</span>").replace(/\s/g, " "));

Я думаю, що це найкращий спосіб зробити це, а потім обробити проміжки. (наприклад, з TweenMax)

TweenMax.staggerFromTo ($ demoText.find ("span"), 0,2, {autoAlpha: 0}, {autoAlpha: 1}, 0,1);


-1

Спробуйте цей код

    function myFunction() {
    var text =(document.getElementById("htext").value); 
    var meow = " <p> <,> </p>";
    var i;


    for (i = 0; i < 9000; i++) {

        text+=text[i] ;



    }

    document.getElementById("demo2").innerHTML = text;

}
</script>
<p>Enter your text: <input type="text" id="htext"/>

    <button onclick="myFunction();">click on me</button>
</p>
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.