2014-02-03 5 views
11

У меня есть строка, и я хотел бы ее отменить. Например, я пишу фильтр AngularDart, который меняет строку. Это просто для демонстрационных целей, но это заставило меня задаться вопросом, как бы я изменил строку.Как изменить строку в Dart?

Пример:

Hello, world 

должен превратиться в:

dlrow ,olleH 

Я должен также рассмотреть строки с юникод символов. Например: 'Ame\u{301}lie'

Что такое простой способ изменить строку, даже если она есть?

+0

Можете привести пример, где это было бы полезно. В настоящее время существует множество ответов, которые не подходят для многих материалов, потому что вы не указали прецедент со строгими ограничениями, чтобы сработала обратная строка. Ни один из ответов пока не работает с простыми вводами, такими как 'Ame \ u {301} lie''. –

+0

@FlorianLoitsch Я писал как угловой фильтр в качестве демонстрации. Было просто создать фильтр, который изменил бы строку. Я уточню в вопросе, что такое мой вариант использования. –

ответ

18

Вопрос не определен. Реверсирование произвольных строк не имеет смысла и приведет к нарушению вывода. Первым (преодолимым) препятствием является Утф-16. Дарт строка кодируется как UTF-16 и задний ход только на кодовые блоках приводит к недействительным строкам:

var input = "Music \u{1d11e} for the win"; // Music for the win 
print(input.split('').reversed.join()); // niw eht rof 

split функция явно предостерегает от этой проблемы (с примером):

Расщепления с пустая строка ('') разбивается на границы кодового блока UTF-16, а не на границах рун [.]

Существует простой исправить это: вместо того, чтобы обратить вспять отдельные кодовые блоки можно поменять местами руны:

var input = "Music \u{1d11e} for the win"; // Music for the win 
print(new String.fromCharCodes(input.runes.toList().reversed)); // niw eht rof cisuM 

Но это еще не все. Руны тоже могут иметь определенный порядок. Это второе препятствие много сложнее решить. Простой пример:

var input = 'Ame\u{301}lie'; // Amélie 
print(new String.fromCharCodes(input.runes.toList().reversed)); // eiĺemA 

Обратите внимание, что акцент на неправильном знаке.

Возможно, существуют другие языки, которые еще более чувствительны к порядку отдельных рун.

Если ввод имеет серьезные ограничения (например, Ascii, или Iso Latin 1), то технически возможны обратные строки. Тем не менее, я еще не видел ни одного случая использования, когда эта операция имела смысл.

Использование этого вопроса в качестве примера для отображения того, что строки имеют операции типа «Список», также не является хорошей идеей. За исключением нескольких случаев использования, строки должны обрабатываться в отношении конкретного языка и с очень сложными методами, которые имеют знание по языку.

В частности, говорящие на родном английском языке должны обратить внимание: строки редко можно обрабатывать, как если бы они были списками отдельных символов. Практически на любом другом языке это приведет к ошибкам программ. (И не заводи меня на toLowerCase и toUpperCase ...).

+0

Я так многому научился от этого простого Q & A, что теперь мне интересно, что случилось с 'toLowerCase' и' toUpperCase'. –

9

Вот один из способов реверсировать ASCII Строки в Dart:

input.split('').reversed.join(''); 
  1. разделить строку на каждом персонаже, создавая список
  2. генерировать итератор, который переворачивает список
  3. присоединиться список (создание новой строки)

Примечание: это не обязательно самый быстрый способ изменить строку. См. Другие ответы на альтернативы.

Примечание: это не относится ко всем строкам unicode.

+0

Это не быстрый способ, потому что он создает список . Если у вас есть строка с большой длиной, она создает множество строк. Одна строка для каждого блока кода в строке ввода. Это неэффективно. – mezoni

+0

Мезони прав: его решение проще и быстрее. –

+0

Спасибо. Я уточню, что мой ответ не является самым быстрым способом. –

3

Попробуйте эту функцию

String reverse(String s) { 
    var chars = s.splitChars(); 
    var len = s.length - 1; 
    var i  = 0; 

    while (i < len) { 
    var tmp = chars[i]; 
    chars[i] = chars[len]; 
    chars[len] = tmp; 
    i++; 
    len--; 
    } 

    return Strings.concatAll(chars); 
} 

void main() { 
    var s = "Hello , world"; 
    print(s); 
    print(reverse(s)); 
} 

(или)

String reverse(String s) { 
    StringBuffer sb=new StringBuffer(); 
    for(int i=s.length-1;i>=0;i--) { 
    sb.add(s[i]); 
    } 
    return sb.toString(); 
} 

main() { 
    print(reverse('Hello , world')); 
} 
+0

Это не работает по причинам, описанным в ответах с более высоким рейтингом. –

2

Я сделал небольшой тест несколько различных вариантов:

String reverse0(String s) { 
    return s.split('').reversed.join(''); 
} 

String reverse1(String s) { 
    var sb = new StringBuffer(); 
    for(var i = s.length - 1; i >= 0; --i) { 
    sb.write(s[i]); 
    } 
    return sb.toString(); 
} 

String reverse2(String s) { 
    return new String.fromCharCodes(s.codeUnits.reversed); 
} 

String reverse3(String s) { 
    var sb = new StringBuffer(); 
    for(var i = s.length - 1; i >= 0; --i) { 
    sb.writeCharCode(s.codeUnitAt(i)); 
    } 
    return sb.toString(); 
} 

String reverse4(String s) { 
    var sb = new StringBuffer(); 

    var i = s.length - 1; 

    while (i >= 3) { 
    sb.writeCharCode(s.codeUnitAt(i-0)); 
    sb.writeCharCode(s.codeUnitAt(i-1)); 
    sb.writeCharCode(s.codeUnitAt(i-2)); 
    sb.writeCharCode(s.codeUnitAt(i-3)); 
    i -= 4; 
    } 

    while (i >= 0) { 
    sb.writeCharCode(s.codeUnitAt(i)); 
    i -= 1; 
    } 

    return sb.toString(); 
} 

String reverse5(String s) { 
    var length = s.length; 
    var charCodes = new List(length); 
    for(var index = 0; index < length; index++) { 
    charCodes[index] = s.codeUnitAt(length - index - 1); 
    } 

    return new String.fromCharCodes(charCodes); 
} 
main() { 
    var s = "Lorem Ipsum is simply dummy text of the printing and typesetting industry."; 

    time('reverse0',() => reverse0(s)); 
    time('reverse1',() => reverse1(s)); 
    time('reverse2',() => reverse2(s)); 
    time('reverse3',() => reverse3(s)); 
    time('reverse4',() => reverse4(s)); 
    time('reverse5',() => reverse5(s)); 
} 

Вот resu л:

reverse0: => 331,394 ops/sec (3 us) stdev(0.01363) 
reverse1: => 346,822 ops/sec (3 us) stdev(0.00885) 
reverse2: => 490,821 ops/sec (2 us) stdev(0.0338) 
reverse3: => 873,636 ops/sec (1 us) stdev(0.03972) 
reverse4: => 893,953 ops/sec (1 us) stdev(0.04089) 
reverse5: => 2,624,282 ops/sec (0 us) stdev(0.11828) 
0

Библиотека More Dart содержит облегченную обертку строк, что делает их вести себя как неизменяемый список символов:

import 'package:more/iterable.dart'; 

void main() { 
    print(string('Hello World').reversed.join()); 
} 
Смежные вопросы