【问题标题】:Pythonic way of getting a value from a list从列表中获取值的 Pythonic 方式
【发布时间】:2015-03-12 10:06:25
【问题描述】:

编辑:添加了问题的 (b) 部分

我有一个长字符串是这样的:

"a=x b=x c=x..."

a,b,c... 始终相同,而 x 则不同。我想要的是让我们说 b=x 但前提是 x 匹配特定的字符串。

到目前为止,我将字符串传递给一个列表,并用空格分隔值,如下所示:

['a=x', 'b=x', 'c=x'...]

a) 只有当 x="something_I_want" 时才能获得 b=x 的最 Pythonic 方式是什么? (已解决)

b) 对于给定的 b,获取 x 的方法是什么?换句话说,我想得到等于我已知值 b 的值。

(b) 的解决方案是:

k = "PROTO="
keep = [ele for ele in x.split() if ele.startswith(k)]
print str(keep[0]).split('=')[1]

类似于@Padraic Cunningham 在下面的答案中建议的内容。有没有更有效的方法来做到这一点?

【问题讨论】:

  • 如果 x 等于你想要的值,你真正想要什么输出?
  • 基本上,x值应该是一个具体的值,但有时不是。如果 x 值等于我想要的值,我想获取整个字符串。
  • 那么你只需要 str.endswith
  • 我编辑了我的答案,您可以理解所有内容或使用生成器表达式与下一个

标签: python string list parsing split


【解决方案1】:

一个简单的方法是通过re

import re
x = "a=x b=i_want_this c=x.. b=sdf b=wer."
k="i_want_this"
print re.findall(r"\bb="+re.escape(k)+r"\b",x)

【讨论】:

  • 别忘了re.escape k
  • 我得到一个空列表。
  • @vks 通常,我将其保存在 .py 文件中,然后在终端中运行。我只是替换了变量 x 和 k 的值。我得到的只是 [ ]。
  • @vks x = "Jun 30 13:07:51 xxxx 内核:15702368.296557 UFW BLOCK IN=eth1 OUT= MAC=so:me:mac SRC=xx.xx.xx.xx DST=xx .xx.xx.xx LEN=40 TOS=0x00 PREC=0x00 TTL=55 ID=47632 PROTO=TCP SPT=58875 DPT=80 WINDOW=65535 RES=0x00 CK FIN URGP=0" k = "TCP"
  • @antonis_man 使用print re.findall(r"\b[^= ]*="+re.escape(k)+r"\b",x)
【解决方案2】:

这似乎就是你要找的东西:

>>> s = 'a=1 b=2 c=3 d=4'
>>> parsed = [x.split('=') for x in s.split()]
>>> whatineed = [k for k, v in parsed if v == '2']
>>> whatineed
['b']

如果所有的值(xs)都不一样,需要做大量的检索,可以将字符串转换成value->keydict:

>>> p = dict(reversed(x.split('=')) for x in s.split())
>>> p
{'1': 'a', '3': 'c', '2': 'b', '4': 'd'}
>>> p['2']
'b'

至于“pythonic”位,当您必须以字符串形式处理结构化数据时,首先将此字符串转换为实际结构(list、dict)会更简洁(因此也更“pythonic”),然后然后检索您需要的数据。在大多数情况下,用 string 函数提取 data 既麻烦又不可靠。

【讨论】:

  • 制作dict 可能无法像s = 'a=1 b=2 c=2 d=4' 那样工作
  • @ferhatelmas:这就是为什么我说:“如果所有值都不同......”
  • 很抱歉没有仔细阅读周围的文字,只检查了代码。仍然习惯于急于寻求答案;)
  • @georg 我收到错误消息:“ValueError: need more than 1 value to unpack”。
  • 仅用于安全拆分一次,以防万一值包含=
【解决方案3】:

如果您只想根据x 的值进行过滤,您可以使用带有str.endswith 的单个列表推导:

keep = [ele for ele in s.split() if ele.endswith("=whatever") ]

使用您的测试字符串:

x = "Jun 30 13:07:51 xxxx kernel: 15702368.296557 UFW BLOCK IN=eth1 OUT= MAC=so:me:mac SRC=xx.xx.xx.xx DST=xx.xx.xx.xx LEN=40 TOS=0x00 PREC=0x00 TTL=55 ID=47632 PROTO=TCP SPT=58875 DPT=80 WINDOW=65535 RES=0x00 CK FIN URGP=0"
k = "=TCP"
keep = [ele for ele in x.split() if ele.endswith(k)]
['PROTO=TCP']

一些时间显示只使用 str.endswith 和 split 是最有效的:

In [49]: timeit [ele for ele in x.split() if ele.endswith(k)]
100000 loops, best of 3: 7.81 µs per loop

In [50]: timeit re.findall(r"\b[^= ]*="+re.escape(k)+r"\b",x)
100000 loops, best of 3: 16.5 µs per loop

In [51]: [ele for ele in x.split() if ele.endswith(k)]
Out[51]: ['PROTO=TCP']

In [52]: re.findall(r"\b[^= ]*="+re.escape(k)+r"\b",x)
Out[52]: ['PROTO=TCP']

如果您只想要第一个匹配项,或者只有一个匹配项:

k = "PROTO="

keep = (ele.split("=")[1] for ele in x.split() if ele.startswith(k))
print(next(keep,""))

TCP

或拆分后:

k = "PROTO="
keep = (ele for ele in x.split() if ele.startswith(k))
print(next(keep,"").split("=")[-1])

【讨论】:

    【解决方案4】:

    可能不是解决问题的最“pythonic”方式,但我认为这是一个安全的解决方案:)..

    def getValueOfString(str, x):
       dict = {}
       for i in s.split():
         item = i.split("=")
         if dict.has_key(item[1]):
           dict[item[1]].append(item[0])
         else:
           dict[item[1]] = [item[0]]
       return dict[x] if dict.has_key(x) else []
    

    【讨论】:

      猜你喜欢
      • 2011-04-23
      • 2015-02-06
      • 2023-03-04
      • 2016-02-11
      • 2019-05-03
      • 2015-10-09
      • 1970-01-01
      • 2017-05-09
      • 2015-04-30
      相关资源
      最近更新 更多