Python разделить список значений на основе условия - PullRequest
1 голос
/ 12 марта 2019

Учитывая, что список значений Python разделен на основе определенных критериев:

    list = ['(( value(name) = literal(luke) or value(like) = literal(music) ) 
     and (value(PRICELIST) in propval(valid))',
    '(( value(sam) = literal(abc) or value(like) = literal(music) ) and 
     (value(PRICELIST) in propval(valid))'] 

Теперь список [0] будет

  (( value(name) = literal(luke) or value(like) = literal(music) ) 
     and (value(PRICELIST) in propval(valid))

Я хочу разделить так, чтобы при повторении он давалЯ:

#expected output
value(sam) = literal(abc)
value(like) = literal(music)

Это тоже, если он начинается со значения и литерала.Сначала я думал о разделении с и, или, но это не сработает, потому что иногда может отсутствовать и, или.

Я пытался:

for i in list:
i.split()
print(i)
#output ['((', 'value(abc)', '=', 'literal(12)', 'or' .... 

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

Ответы [ 4 ]

1 голос
/ 12 марта 2019

@ Duck_dragon

Ваши строки в вашем списке во вступительном посте были отформатированы таким образом, что они вызывают синтаксическую ошибку в Python. В приведенном ниже примере я отредактировал его для использования '''

>>> import re
>>> list = ['''(( value(name) = literal(luke) or value(like) = literal(music) ) 
 and (value(PRICELIST) in propval(valid))''',
'''(( value(sam) = literal(abc) or value(like) = literal(music) ) and 
 (value(PRICELIST) in propval(valid))''']


#Simple findall without setting it equal to a variable so it returns a list of separate strings but which you can't use
#You can also use the *MORE SIMPLE* but less flexible regex:  '([a-zA-Z]+\([a-zA-Z]+\)[\s=]+[a-zA-Z]+\([a-zA-Z]+\))'
>>> for item in list:
        re.findall('([a-zA-Z]+(?:\()[a-zA-Z]+(?:\))[\s=]+[a-zA-Z]+(?:\()[a-zA-Z]+(?:\)))', item)    

    ['value(name) = literal(luke)', 'value(like) = literal(music)']
    ['value(sam) = literal(abc)', 'value(like) = literal(music)']

.

Чтобы сделать этот шаг дальше и дать вам массив, с которым вы можете работать:

>>> import re
>>> list = ['''(( value(name) = literal(luke) or value(like) = literal(music) ) 
 and (value(PRICELIST) in propval(valid))''',
'''(( value(sam) = literal(abc) or value(like) = literal(music) ) and 
 (value(PRICELIST) in propval(valid))''']


#Declaring blank array found_list which you can use to call the individual items
>>> found_list = []
>>> for item in list:
        for element in re.findall('([a-zA-Z]+(?:\()[a-zA-Z]+(?:\))[\s=]+[a-zA-Z]+(?:\()[a-zA-Z]+(?:\)))', item):
            found_list.append(element)


>>> found_list
['value(name) = literal(luke)', 'value(like) = literal(music)', 'value(sam) = literal(abc)', 'value(like) = literal(music)']

.

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

>>> import re
>>> list = ['''(( value(name) = literal(luke) or value(like) = literal(music) ) 
and (value(PRICELIST) in propval(valid))''',
'''(( value(sam) = literal(abc) or value(like) = literal(music) ) and 
(value(PRICELIST) in propval(valid))''',
'''(value(PICK_SKU1) = propval(._sku)''', '''propval(._amEntitled) > literal(0))''']


>>> found_list = []
>>> for item in list:
        for element in re.findall('([\w\.]+(?:\()[\w\.]+(?:\))[\s=<>(?:in)]+[\w\.]+(?:\()[\w\.]+(?:\)))', item):
            found_list.append(element)

>>> found_list
['value(name) = literal(luke)', 'value(like) = literal(music)', 'value(PRICELIST) in propval(valid)', 'value(sam) = literal(abc)', 'value(like) = literal(music)', 'value(PRICELIST) in propval(valid)', 'value(PICK_SKU1) = propval(._sku)', 'propval(._amEntitled) > literal(0)']

.

Редактировать: Или это то, что вы хотите?

>>> import re
>>> list = ['''(( value(name) = literal(luke) or value(like) = literal(music) ) 
 and (value(PRICELIST) in propval(valid))''',
'''(( value(sam) = literal(abc) or value(like) = literal(music) ) and 
 (value(PRICELIST) in propval(valid))''']


#Declaring blank array found_list which you can use to call the individual items
>>> found_list = []
>>> for item in list:
        for element in re.findall('([a-zA-Z]+(?:\()[a-zA-Z]+(?:\))[\s=<>(?:in)]+[a-zA-Z]+(?:\()[a-zA-Z]+(?:\)))', item):
            found_list.append(element)


>>> found_list
['value(name) = literal(luke)', 'value(like) = literal(music)', 'value(PRICELIST) in propval(valid)', 'value(sam) = literal(abc)', 'value(like) = literal(music)', 'value(PRICELIST) in propval(valid)']

Дайте мне знать, если вам нужно объяснение.

.

@ Федор Куцепин

В вашем примере выньте your_list_ и замените его на OP list, чтобы избежать путаницы. Во-вторых, у вашего for loop отсутствует :, выдающий синтаксические ошибки

1 голос
/ 12 марта 2019

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

Учитывая ваш комментарий выше, который я не мог понять, это то, что вы хотите? Я изменил список, чтобы добавить другие упомянутые вами значения:

>>> import re
>>> list = ['''(( value(name) = literal(luke) or value(like) = literal(music) ) 
and (value(PRICELIST) in propval(valid))''',
'''(( value(sam) = literal(abc) or value(like) = literal(music) ) and 
(value(PRICELIST) in propval(valid))''',
'''(value(PICK_SKU1) = propval(._sku)''', '''propval(._amEntitled) > literal(0))''']


>>> found_list = []
>>> for item in list:
        for element in re.findall('([\w\.]+(?:\()[\w\.]+(?:\))[\s=<>(?:in)]+[\w\.]+(?:\()[\w\.]+(?:\)))', item):
            found_list.append(element)

>>> found_list
['value(name) = literal(luke)', 'value(like) = literal(music)', 'value(PRICELIST) in propval(valid)', 'value(sam) = literal(abc)', 'value(like) = literal(music)', 'value(PRICELIST) in propval(valid)', 'value(PICK_SKU1) = propval(._sku)', 'propval(._amEntitled) > literal(0)']

Пояснение:

  • Предварительное примечание - я изменил [a-zA-Z0-9\._]+ на [\w\.]+, поскольку они означают, по сути, одно и то же, но один из них более лаконичен. Я объясню, какие символы охватываются этими запросами на следующем шаге
  • С ([\w\.]+, отмечая, что это «незакрытый», означающий, что я запускаю регулярное выражение для захвата всего в следующем запросе, я говорю ему начинать с захвата всех символов, которые находятся в диапазоне a-z, A-Z и _, а также экранированный период (.)
  • С (?:\() Я говорю, что захваченный запрос должен содержать экранированную «открывающую» скобку (()
  • С помощью [\w\.]+(?:\)) я говорю, что следуйте этой скобке снова со словами, обозначенными на втором шаге, но на этот раз через (?:\)) Я говорю, что следуйте за ними через экранированную "закрывающую" скобку ())
  • Это [\s=<>(?:in)]+ отчасти безрассудно, но ради читабельности и предположения, что ваши строки будут оставаться относительно согласованными, это говорит о том, что за «закрывающей скобкой» должны следовать "whitespace", =, a <, > или слово in, в любом порядке, сколько бы раз они ни возникали последовательно. Он безрассуден, потому что он также будет соответствовать таким вещам, как << <, = in > = и т. Д. Чтобы сделать его более конкретным, можно легко потерять захваты, хотя
  • С помощью [\w\.]+(?:\()[\w\.]+(?:\)) я повторяю еще раз, найдите символы слова, начиная с шага 1, за которыми следует «открывающая скобка», за которой снова следуют символы слова, а затем «закрывающая скобка»
  • С помощью ) я закрываю «незакрытую» группу перехвата (помните, что первая группа перехвата, начатая как «незакрытая»), чтобы заставить механизм регулярных выражений перехватить весь набросок, который я обрисовал

Надеюсь, это поможет

0 голосов
/ 12 марта 2019

Не говорю, что вы должны, но вы определенно можете использовать парсер PEG здесь:

from parsimonious.grammar import Grammar
from parsimonious.nodes import NodeVisitor

data = ['(( value(name) = literal(luke) or value(like) = literal(music) ) and (value(PRICELIST) in propval(valid))',
        '(( value(sam) = literal(abc) or value(like) = literal(music) ) and (value(PRICELIST) in propval(valid))']

grammar = Grammar(
    r"""
    expr        = term (operator term)*
    term        = lpar* factor (operator needle)* rpar*
    factor      = needle operator needle

    needle      = word lpar word rpar

    operator    = ws? ("=" / "or" / "and" / "in") ws?
    word        = ~"\w+"

    lpar        = "(" ws?
    rpar        = ws? ")"
    ws          = ~r"\s*"
    """
)

class HorribleStuff(NodeVisitor):
    def generic_visit(self, node, visited_children):
        return node.text or visited_children

    def visit_factor(self, node, children):
        output, equal = [], False

        for child in node.children:
            if (child.expr.name == 'needle'):
                output.append(child.text)
            elif (child.expr.name == 'operator' and child.text.strip() == '='):
                equal = True

        if equal:
            print(output)

for d in data:
    tree = grammar.parse(d)
    hs = HorribleStuff()
    hs.visit(tree)

Это дает

['value(name)', 'literal(luke)']
['value(sam)', 'literal(abc)']
0 голосов
/ 12 марта 2019

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

, например:

first, rest = your_list_[1].split(') and'):
for item in first[2:].split('or')
    print(item)
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...