У меня такая структура данных:
var = [['x_A_B', 1], ['x_A_C', 1], ['x_B_A', 1], ['x_B_D', 1], ['x_C_A', 1], ['x_C_D', 1], ['x_D_B', 1], ['x_D_C', 1]]
Я хотел бы извлечь эти значения как
var2 = [('A', 'B'), ('A', 'C'), ('B', 'A'), ('B', 'D'), ('C', 'A'), ('C', 'D'), ('D', 'B'), ('D', 'C')]
В настоящее время я использую следующую строку
var2 = [(item[0].split("_")[1], item[0].split("_")[2]) for item in var]
а писать утомительно, да еще и тот же split вычисляет два раза.
Есть ли способ записать это компактно, может быть, с ключевыми словами with ... as, что-то вроде этого?
# not working
var2 = [(u, v) with item[0].split("_") as _, u, v for item in var]
Обновлено: Я искал более общее решение, в котором я мог бы использовать произвольные индексы разделенной строки с произвольной длиной подстрок, я просто использовал неподходящий пример. См. Решение, которое я принял.






Зачем вообще использовать split? Вы знаете точные индексы букв, которые хотите.
>>> var = [['x_A_B', 1], ['x_A_C', 1], ['x_B_A', 1], ['x_B_D', 1], ['x_C_A', 1], ['x_C_D', 1], ['x_D_B', 1], ['x_D_C', 1]]
>>> [(x[0][2], x[0][4]) for x in var]
[('A', 'B'), ('A', 'C'), ('B', 'A'), ('B', 'D'), ('C', 'A'), ('C', 'D'), ('D', 'B'), ('D', 'C')]
I am interested in a more general case, suppose there can be 'x_word1_word2' variable names.
В этом случае internet_user дал вам решение в комментариях.
>>> var = [['x_A_B', 1], ['x_word1_word2']]
>>> [tuple(x[0].rsplit('_', 2)[1:]) for x in var]
[('A', 'B'), ('word1', 'word2')]
(Я использовал rsplit, ограниченный двумя разделениями, для очень незначительного повышения эффективности.)
Меня интересует более общий случай, допустим, могут быть имена переменных x_word1_word2.
В общем случае это будет:
[tuple(item[0].split('_')[1:3]) for item in var]
И самый общий случай:
indices = {1,2}
[tuple([x for i, x in enumerate(item[0].split('_')) if i in indices]) for item in var]
Но если у вас есть два индекса, расположенных один рядом с другим, это было бы слишком много.
Да, в данном случае это работает, @internet_user также предложил это. Но что делать, если нужные мне индексы не идут подряд, т.е. мне нужны 0 и 2?
@Rolf, ты все время меняешь вопрос, и, честно говоря, это начинает раздражать.
@timgeb Извините за это, я просто несколько раз сталкивался с этой проблемой, и меня интересовало очень общее решение. Но я признаю, что приведенный мною пример проще.
Ты можешь использовать:
[tuple(x[0].split('_')[1:]) for x in var]
out: [('A', 'B'), ('A', 'C'), ('B', 'A'), ('B', 'D'), ('C', 'A'), ('C', 'D'), ('D', 'B'), ('D', 'C')]
Другие ответы уже говорят о вашем конкретном случае. В более общем случае, если вы наблюдаете, что одно и то же значение появляется в понимании несколько раз ...
var2 = [(item[0].split("_")[1], item[0].split("_")[2]) for item in var]
^ ^
и вы бы хотели избежать этого повторения. Это примерно так?
Один из способов - использовать вложенный цикл, но на самом деле это трюк с кодом для игры в гольф ...
[(parts[1], parts[2] for item in var for parts in [item[0].split("_")]]
# or
[(a, b) for item in var for (_, a, b) in [item[0].split("_")]]
но да, это не пройдет проверку кода ...
Как насчет того, чтобы вместо этого написать функцию?
def extract_parts(item):
parts = item[0].split("_")
return parts[1], parts[2]
[extract_parts(item) for item in var]
# or:
map(extract_parts, var)
Искал однострочное решение. Две написанные вами версии в порядке, но ответ, который я принял от abccd, немного яснее. По крайней мере, так работает мой мозг.
Конечно. Я лично нахожу однострочную версию слишком умной для собственного блага, и я бы предпочел извлечь помощника.
Чтобы ответить на ваш вопрос с помощью подхода, аналогичного вашему примеру, и включая ваш комментарий:
Yes that works in this case, @internet_user also suggested this. But what if the indices I need are not consecutive, i.e. I need 0 and 2?
Синтаксис with...as... предназначен для диспетчеров контекста, который имеет совершенно другое применение. Однако можно обойтись без распаковки цикла for.
var = [['x_A_B', 1], ['x_A_C', 1], ['x_B_A', 1], ['x_B_D', 1], ['x_C_A', 1], ['x_C_D', 1], ['x_D_B', 1], ['x_D_C', 1]]
var2 = [(u, v) for item in var for _, u, v in (item[0].split("_"), )]
print(var2)
Я искал именно это.
item[0].split("_")[1:]