如何从包含 nan 的类列表字符串中获取字符串列表?
How to get list of strings from list-like string that includes nan?
这是玩具示例,我有这样的字符串:
import numpy as np
z = str([np.nan, "ab", "abc"])
印刷 看起来像 "[nan, 'ab', 'abc']"
但我必须处理 z = str([np.nan, "ab", "abc"])
我想从 z
字符串列表中获取不包括 nan:
zz = ["ab", "abc"]
要清楚:z
是输入(字符串,看起来像列表),zz
是想要的输出(列表)
如果 z
不包含 nan 就没有问题,这样 ast.literal_eval(z)
就可以完成工作,但是对于 nan 我会收到有关格式错误的节点或字符串的错误。
注意: np.nan
不必是第一个。
许多解决方案其中之一是
z = [nan, 'string', 'another_one']
string_list = []
for item in z :
# find the object come from str Class and Append it to the list
if item.__class__ == str:
string_list.append(item)
使用 filter() 函数:
list(filter(lambda f: type(f)==str, z))
怎么样:
eval(z,{'nan':'nan'}) # if you can tolerate then:
[i for i in eval(z,{'nan':'nan'}) if i != 'nan']
可能有安全方面的考虑。
ast.literal_eval
优于 eval
正是因为它允许的语句集非常有限。如文档中所述:“安全地评估表达式节点或包含 Python 文字或容器显示的字符串。提供的 字符串或节点可能仅包含以下 Python 文字结构:字符串、字节、数字、元组、列表、字典、集合、布尔值、None 和省略号。” np.nan
是其中的 none,因此无法对其进行评估。
处理这个问题的选择很少。
- 通过在对字符串进行评估之前对其进行操作来删除
nan
。如果您还想避免从实际字符串中删除 nan,则可能会出现问题。
- 不建议 - 安全风险 - 如果你在命名空间
中定义 nan 变量,标准 eval
可以解决这个问题
- 最后,我认为最好的选择也是最难实现的:就像 here 解释的那样,你获取
ast
的源代码,将其子类化并重新实现 literal_eval
它知道如何自己处理 nan
字符串的一种方式。
据我了解,您的目标是解析 csv 或类似文件。
如果您希望 trade-off 解决方案在大多数情况下都能正常工作,您可以使用正则表达式去掉“nan”。它会在包含子字符串 nan,
(带逗号)的字符串上失败,但这似乎是一种不太可能的边缘情况。值得和你爆料的真实数据。
z = str([np.nan, "ab", np.nan, "nan,", "abc", "x nan , y", "x nan y"])
import re
literal_eval(re.sub(r'\bnan\s*,\s*', '', z))
输出:['ab', '', 'abc', 'x y', 'x nan y']
这是玩具示例,我有这样的字符串:
import numpy as np
z = str([np.nan, "ab", "abc"])
印刷 看起来像 "[nan, 'ab', 'abc']"
但我必须处理 z = str([np.nan, "ab", "abc"])
我想从 z
字符串列表中获取不包括 nan:
zz = ["ab", "abc"]
要清楚:z
是输入(字符串,看起来像列表),zz
是想要的输出(列表)
如果 z
不包含 nan 就没有问题,这样 ast.literal_eval(z)
就可以完成工作,但是对于 nan 我会收到有关格式错误的节点或字符串的错误。
注意: np.nan
不必是第一个。
许多解决方案其中之一是
z = [nan, 'string', 'another_one']
string_list = []
for item in z :
# find the object come from str Class and Append it to the list
if item.__class__ == str:
string_list.append(item)
使用 filter() 函数:
list(filter(lambda f: type(f)==str, z))
怎么样:
eval(z,{'nan':'nan'}) # if you can tolerate then:
[i for i in eval(z,{'nan':'nan'}) if i != 'nan']
可能有安全方面的考虑。
ast.literal_eval
优于 eval
正是因为它允许的语句集非常有限。如文档中所述:“安全地评估表达式节点或包含 Python 文字或容器显示的字符串。提供的 字符串或节点可能仅包含以下 Python 文字结构:字符串、字节、数字、元组、列表、字典、集合、布尔值、None 和省略号。” np.nan
是其中的 none,因此无法对其进行评估。
处理这个问题的选择很少。
- 通过在对字符串进行评估之前对其进行操作来删除
nan
。如果您还想避免从实际字符串中删除 nan,则可能会出现问题。 - 不建议 - 安全风险 - 如果你在命名空间 中定义 nan 变量,标准
- 最后,我认为最好的选择也是最难实现的:就像 here 解释的那样,你获取
ast
的源代码,将其子类化并重新实现literal_eval
它知道如何自己处理nan
字符串的一种方式。
eval
可以解决这个问题
据我了解,您的目标是解析 csv 或类似文件。
如果您希望 trade-off 解决方案在大多数情况下都能正常工作,您可以使用正则表达式去掉“nan”。它会在包含子字符串 nan,
(带逗号)的字符串上失败,但这似乎是一种不太可能的边缘情况。值得和你爆料的真实数据。
z = str([np.nan, "ab", np.nan, "nan,", "abc", "x nan , y", "x nan y"])
import re
literal_eval(re.sub(r'\bnan\s*,\s*', '', z))
输出:['ab', '', 'abc', 'x y', 'x nan y']