【问题标题】:Compact way using generators/"with ... as" in Python在 Python 中使用生成器/“with ... as”的紧凑方式
【发布时间】:2018-03-19 11:59:24
【问题描述】:

我有以下数据结构:

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]

编辑:我正在寻找一个更通用的解决方案,我可以使用具有任意长度子字符串的拆分字符串的任意索引,我只是使用了一个不正确的示例。查看我接受的解决方案。

【问题讨论】:

  • item[0].split("_")[1:]

标签: python generator with-statement


【解决方案1】:

一般情况是:

[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 抱歉,我只是多次偶然发现这个问题,我对一个非常通用的解决方案很感兴趣。但我承认我给出的当前示例更简单。
【解决方案2】:

为什么还要使用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')]

我对更一般的情况感兴趣,假设可以有 'x_word1_word2' 变量名。

那么在这种情况下,internet_user 在 cmets 中为您提供了解决方案。

>>> 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 变量名。
【解决方案3】:

用与您的示例类似的方法回答您的问题,包括您的comment

是的,在这种情况下有效,@internet_user 也建议这样做。但 如果我需要的索引不是连续的,即我需要 0 和 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)

【讨论】:

  • 我正在寻找这个。
【解决方案4】:

其他答案已经在谈论您的具体情况。在更一般的情况下,如果您观察到同一个值在理解中出现多次...

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的回答就清楚了一点。至少它是我大脑工作方式中最接近的。
  • 当然。我个人觉得单行版本有点太聪明了,我宁愿提取一个助手。
【解决方案5】:

你可以使用:

[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')]

【讨论】:

    猜你喜欢
    • 2019-02-19
    • 1970-01-01
    • 2015-08-06
    • 1970-01-01
    • 2010-12-19
    • 1970-01-01
    • 1970-01-01
    • 2018-04-18
    • 1970-01-01
    相关资源
    最近更新 更多