Regex (или другое предложение) для разбора хэштега - PullRequest
3 голосов
/ 17 ноября 2010

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

#p3                  -> p = 3
#h4                  ->         h = [ 4 ]
#h4,h6               ->         h = [ 4, 6 ]
#p3,h4,h6            -> p = 3,  h = [ 4, 6 ]
#h4,h6,p3            -> p = 3,  h = [ 4, 6 ]
#h4s2,6,10           ->         h = [ 4 ],    s = { "4": [ 2, 6, 10 ] }
#h4s2,6,10,h6s5      ->         h = [ 4, 6 ], s = { "4": [ 2, 6, 10 ] , "6": [ 5 ] }
#p20h4s2,6,10,h6s5,1 -> p = 20, h = [ 4, 6 ], s = { "4": [ 2, 6, 10 ] , "6": [ 5, 1 ] }

Как я уже сказал, я думаю, что регулярное выражение может быть моей лучшей ставкой, но это также слабое место для чего-то сложного.

Если у вас есть другие предложения / решения, тогда я приветствую их. Я мог бы сделать это, используя if/else с большим количеством indexOf и splits и так далее ... но я уверен, что должен быть лучший способ, чем этот.

Обновление: Вывод слева лучше всего рассматривать как объяснение. Хотя это и является желаемым конечным результатом, решение регулярных выражений не должно полностью решать проблему, но, возможно, поможет мне в этом. Кроме того, повторюсь, я работаю в Javascript .

Ответы [ 3 ]

5 голосов
/ 17 ноября 2010

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

Судя по всему, у вас есть три типа токенов: p, h и s. Каждый токен представляет собой букву, за которой следует число (за которым следуют дополнительные цифры в случае s).

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

Давайте возьмем эту строку: #p20h4s2,6,10,h6s5,1. Пока еще есть ввод, вы будете создавать последовательность токенов на основе оставшегося ввода.

Ваш первый токен p со значением 20. Тогда у вас есть h со значением 4. Затем s со значением [2,6,10] и так далее. Чтобы определить, какой токен есть какой, используйте очень простое регулярное выражение. p выражение может быть p\d+. h может быть h\d+. s похоже, что это будет s(\d+)(,\d+)*.

Результатом вашего шага токенизации является последовательность таких объектов: { p(20), h(4), s(2,6,10), h(6), s(5,1) }. На этом этапе вы можете решить, что s(2,6,10) является частью h(4), и построить свою структуру, не беспокоясь о строковом представлении структуры.

Теперь, что касается фактической реализации этого в JavaScript, это не будет слишком сложно. Последовательность токенов может быть массивом, и вы можете найти токены, используя блоки if / else и приведенные выше регулярные выражения.

Важным является разделение части, в которой вы используете строковое представление (токенизация), и части, в которой вы используете абстрактное представление (синтаксический анализ). Концептуально все становится намного проще. Также проще добавлять новые типы токенов, если они понадобятся вам позже.

2 голосов
/ 17 ноября 2010

Вот некоторый код для этого.

var p, h = [], s = {};

var re = /[ph][0-9]+|s[0-9,]*[0-9]/g;
var a;
while ((a = re.exec(myhashtag)) !== null) {
    var first = a[0].substring(0, 1);
    var rest = a[0].substring(1);
    if (first == 'p')
        p = parseInt(rest);
    else if (first == 'h')
        h.push(parseInt(rest));
    else {
        a = rest.split(',');
        for (var i = 0; i < a.length; i++)
            a[i] = parseInt(a[i]);
        s[h[h.length - 1]] = a;
    }
}

Используется только регулярное выражение для поиска всех частей хэштега, которые выглядят как p3 или h4 или s3,4,5.Остальное просто обычный JavaScript.

Этот код очень слабый.Если в хэштеге содержится мусор, который не может быть проанализирован, например, #p3_banana_*q4, этот код просто игнорирует его.Вероятно, было бы лучше написать более строгий код, который выдает ошибку, если хэштег содержит такую ​​ерунду.

0 голосов
/ 17 ноября 2010

Регулярные выражения предназначены для определения наличия заданного шаблона и, возможно, воздействия на него (замены, удаления и т. Д.). Вы хотите сделать больше, чем это; вы хотите определить, присутствует ли шаблон, а затем выполнить какой-то анализ на основе этого. Если бы это был я, я бы выполнил это следующим образом (псевдокод ниже):

if(string_begins_with('#')) {
    if(string_contains('p')) {
        // get numbers following using some "CSV-to-array" function
    }

    if(string_contains('h') {
        foreach('h') {
            // check for 's' following, do csv-to-array thing
        }
    }
}

РЕДАКТИРОВАТЬ: если вы действительно хотите пойти по этому пути, вам придется использовать предвкушения. Предполагая, что p зафиксировано в начале:

/
^\#
(p[\d,]+)?   # find the 'p'
(            # beginning of 'find the "h"' code
    h([[0-9],])  # find the 'h'
    (?=          # beginning of lookahead for 's'
        (s([[0-9],])+)?  # code for s, including a final ? since it may not 
                         # be there at all. I'm not sure if this part will work.
    )           # end of lookahead
)+            # end of code for 'h', + since you may have more than one 'h'
/

Это, вероятно, требует немного работы, но это начало.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...