Действительно ли это - плохой шаблон? (Переключатель внутри для/цикл foreach)

Ваши первые два предложения противоречат друг другу. «в \w, но не в \d» включает в себя подчеркивание. Я предполагаю из вашего третьего предложения, что вы не хотите подчеркнуть.

Использование диаграммы Венна на обороте конверта помогает. Давайте посмотрим на то, что нам НЕ нужно:

(1) символы, которые не соответствуют \w (т.е. не хотят ничего, кроме букв, цифр или подчеркивания) => \W
(2) цифр => \d
(3) подчеркивание => _

Так что нам не нужно ничего в классе символов [\W\d_] и, следовательно, нам нужно что-нибудь из класса символов [^\W\d_]

Вот простой пример (Python 2.6).

>>> import re
>>> rx = re.compile("[^\W\d_]+", re.UNICODE)
>>> rx.findall(u"abc_def,k9")
[u'abc', u'def', u'k']

Дальнейшие исследования показывают несколько особенностей этого подхода:

>>> import unicodedata as ucd
>>> allsorts =u"\u0473\u0660\u06c9\u24e8\u4e0a\u3020\u3021"
>>> for x in allsorts:
...     print repr(x), ucd.category(x), ucd.name(x)
...
u'\u0473' Ll CYRILLIC SMALL LETTER FITA
u'\u0660' Nd ARABIC-INDIC DIGIT ZERO
u'\u06c9' Lo ARABIC LETTER KIRGHIZ YU
u'\u24e8' So CIRCLED LATIN SMALL LETTER Y
u'\u4e0a' Lo CJK UNIFIED IDEOGRAPH-4E0A
u'\u3020' So POSTAL MARK FACE
u'\u3021' Nl HANGZHOU NUMERAL ONE
>>> rx.findall(allsorts)
[u'\u0473', u'\u06c9', u'\u4e0a', u'\u3021']

U + 3021 (HANGZHOU NUMERAL ONE) трактуется как числовое (следовательно, оно совпадает с \ w), но похоже, что Python интерпретирует «цифра» означает «десятичная цифра» (категория Nd), поэтому она не совпадает с \ d

U + 2438 (МАЛЕНЬКИЙ БУКВЫ ИЗ ЛАТИНСКОЙ КРУГЛЫЙ Y) не совпадает с \ w

Все Идеограммы CJK классифицируются как «буквы» и, таким образом, соответствуют \ w

. Независимо от того, является ли какой-либо из вышеуказанных 3 пунктов проблемой, или нет, такой подход является лучшим, что вы получите из модуля re, выпущенного в настоящее время. Синтаксис типа \ p {letter} находится в будущем.

8
задан Magic Hat 31 October 2009 в 01:22
поделиться

6 ответов

Сопоставление ваших функций с ключами в словарном / ассоциативном массиве является обычным подходом для этой ситуации (как упомянул @jldupont) - не только в PHP, но и во многих динамических языках с ассоциативными массивами. Например, Python и Lua даже не имеют оператора switch - это практически единственный способ имитировать переключатель.

Рассмотрим такой подход:

<?
$arr[] = "bye";
$arr[] = "hi";

function sayHi() { print("Hello.\n"); }
function sayBye() { print("Goodbye.\n"); }

$funcs["hi"] = sayHi;
$funcs["bye"] = sayBye;

foreach($arr as $k){
    $funcs[$k]();
}

?>

Вывод:

Goodbye.
Hello.

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

15
ответ дан 5 December 2019 в 06:38
поделиться

Я обычно использую переключатель в цикле foreach. IMHO менее грязный, чем куча if.

Вы можете поместить свой переключатель в другую функцию, например:

foreach($array as $key => $value) {
   doTransaction($key , $value);
}

...

function doTransaction($key, $value){
     switch($key) {
        case 'something':
            doSomething($value);
            break;
        case 'somethingelse':
            doSomethingElse($value);
           break;
    }
}
4
ответ дан 5 December 2019 в 06:38
поделиться

Есть (по крайней мере) еще одна возможность: использовать поиск по словарю для передачи работы функции.

Найдите функцию, используя $ key в качестве «ключа», получите ссылку на функцию и примените его с параметром $ value.

Простите меня, но мой PHP-fu немного устарел.

1
ответ дан 5 December 2019 в 06:38
поделиться

Попробуйте следующее:

Выполните каждую версию - с переключатель и с if - миллион раз. Время каждого запуска.

Сообщите нам, какой из них работает быстрее.

0
ответ дан 5 December 2019 в 06:38
поделиться

Ничего страшного в этом нет.

Если у вас всего 2 или 3 элемента, я бы выбрал if просто ради сложности кода. Если у вас их больше пяти, я бы определенно пошел с переключателем ...

0
ответ дан 5 December 2019 в 06:38
поделиться

Это неплохое решение, но, как всегда, есть альтернативы. Например, вы можете избавиться от оператора switch и использовать интерпретируемый обработчик для строк. Это похоже на список указателей на функции, но вам не нужно обновлять список, чтобы добавить новое поведение; об этом позаботится простое добавление новой функции в обработчик.

$array = array(
  "something" => "itsasecret",
  "somethingelse" => "i can't tell you",
);

class Handler {
  static function something($value) {
    printf("something: %s\n", $value);
  }

  static function somethingelse($value) {
    printf("somethingelse: %s\n", $value);
  }
}

$handler = new Handler();
foreach($array as $key => $value) {
  $handler->$key($value);
}

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

5
ответ дан 5 December 2019 в 06:38
поделиться
Другие вопросы по тегам:

Похожие вопросы: