【问题标题】:How to scan a list for a partial appearance using a dictionary?如何使用字典扫描列表的部分外观?
【发布时间】:2019-03-02 23:02:32
【问题描述】:

我正在尝试使用字典来扫描字符串列表以查看它是否出现在字符串中,例如假设我有一个 {'C99':1, 'C4':1} 字典['C99C2C3C5', 'C88C4'] 的列表,那么新列表将是 ['1','1'] 因为 'C99' 出现在字符串 'C99C2C3C4' 中,而 'C4' 出现在 'C88C4' 中。

我目前的做法是:

import re

dict = {'C99': 1,'C15':1}
ComponentList = ['C1C15C99', 'C15', 'C17']

def func(s):
    for k, v in dict.items():
        if all(i in s for i in re.findall('\w\d', k)):
            return v
    else:
        return 0

ComponentList = [func(i) for i in ComponentList]

输出:

[1, 1, 1]

想要的输出:

[1,1,0]

为了澄清,如果这是我的系统:

my_dict = {'C1C55C99': 1, 'C17': 1, 'C3': 1}
component_list = ['C1C15C55C99', 'C15', 'C17']

因为“C1C55C99”出现在“C1C15C55C99”中,我希望将值更改为字典值以提供输出:

results = ['1','0','1']

但是,当组件编号超过 C9 时,此方法不起作用,希望有人可以帮助我修复,因此它可以用于 Cx,并解释为什么以前的方法不起作用。

谢谢本

【问题讨论】:

  • 你的字典真的叫dict吗?这是一个 Python 内置的,所以我会注意不要将它用作变量名。
  • 我也看不出在你的代码中使用正则表达式的真正目的。你不能检查if k in s:吗?
  • 这个问题有歧义。如果dict = ['A': 1, 'B': 1, 'C': 2, 'D': 3] 并且您的列表是['A', 'AA', 'AB', 'AC', 'ABC', 'ABCD'],输出应该是什么?
  • 嗨,使用 if 'k in s:' 的问题是如果 {'C1':1} 在我的字典中,那么如果列表包含 ['C19'] 它仍然会更改 C19为 1,因为 C1(来自字典)出现在 ['C19'] 中。有什么办法可以规避吗?
  • 字典值总是 1 所以如果我有一个 dict = ['A': 1, 'B': 1, 'C': 1, 'D': 1] 流行列表将是 [0,0,0,0,0,0]

标签: python arrays python-3.x string list


【解决方案1】:

从您的 cmets 来看,在我看来,您的组件列表中的字符 'C' 很重要,因为您似乎想要区分 'C11''C1'

顺便说一句,我完全同意@martineau 在python 中始终使用标准命名。 CamleCasingLikeThis 应该只保留给类名,你应该使用lower_case_like_this 作为一般变量,而不是大写。

让我们来看看如何做到这一点。

my_dict = {'C99': 1, 'C15': 1, 'C1': 1}
component_list = ['C1C15C99', 'C15', 'C17']

result = []

# first convert my_dict to a list of numbers ['99', '15', '1']
elements = [element[1:] for element in my_dict.keys()]

# for every component you want to characterize
for component in component_list:

    # a flag to know if we found any element in this component
    found = False

    # split the string by the 'C' character to get its sub element numbers
    # for example 'C1C15C99'.split('C') == ['', '1', '15', '99']
    for sub_elem in component.split('C'):

        # make sure sub_elem is not an empty string
        if sub_elem:

            # check if this sub element exists in elements
            if sub_elem in elements:

                found = True

                # exit the inner loop
                break

    # convert the boolean to int (either 0 or 1)
    # and finally add this to the result
    result.append(int(found))

print(result)
# [1, 1, 0]

到目前为止,我一直假设my_dict 只能采用像 C1 或 C6 这样的单数组件,而不能像 C12C14 这样的复合组件。从您最新的comment 看来,情况并非如此。另外两件事突然变得清晰:my_dict 可以包含组件的组合,并且在检查另一个组件中是否存在时,顺序无关紧要。例如,C1C2 确实存在于 C5C2C7C1 中,但 C1C2 存在于 C1 中,因为两个子组件都必须存在。

这非常重要,它彻底改变了问题。为了将来参考,请确保从一开始就详尽地描述您的问题。

my_dict = {'C99': 1, 'C15': 1, 'C1': 1, 'C1C55C99': 1, 'C99C6': 1, 'C2C4C18': 1}
component_list = ['C1C15C99', 'C15', 'C17', 'C8C6C80C99', 'C6', 'C55C2C4C18C7', 'C55C1', 'C18C4']

result = []

# first convert my_dict to a list of lists containing singular elements
elements = [element.split('C')[1:] for element in my_dict.keys()]
# elements = [['2', '4', '18'], ['99'], ['1'], ['15'], ['99', '6'], ['1', '55', '99']]

for component in component_list:

    found = False

    # gather the sub elements for this components
    comp_elements = component.split('C')[1:]

    for composite_element in elements:

        element_exists = True

        # check if every singular element in this element is present in component
        for signular_element in composite_element:

            if signular_element not in comp_elements:
                element_exists = False
                break

        if element_exists:
            found = True
            break

    result.append(int(found))

print(result)
# [1, 1, 0, 1, 0, 1, 1, 0]

【讨论】:

  • 嗨,Darksky,我现在已经更改了变量名,感谢您的提醒。有了这段代码,假设我有一个字典和 my_dict = {'C1C55C99': 1, 'C17': 1, 'C3': 1}, component_list = ['C1C15C55C99', 'C15', 'C17'] 的列表,因为字典中的“C1C5C99”确实出现在“C1C15C55C99”中,它应该更改为字典值 1,但不会。希望你能帮忙。本
  • 如果我以后有任何关于不浪费任何人时间的问题,我一定会添加更全面的描述。非常感谢您的帮助!
【解决方案2】:

我不擅长一个衬里,但它比你的简单得多,而且不需要使用正则表达式,只需使用if x in y

def func(s):
for k, v in dict.items():
    if k in s:
        return v
return 0

【讨论】:

  • 嗨,问题是如果 {'C1':1} 在我的字典中,那么如果列表包含 ['C19'] 它仍然会将 C19 更改为 1,因为 C1 出现在 [ 'C19']。有什么办法可以规避吗?
  • 哦,所以也许您应该使用正则表达式来拆分其中包含多个字母的组件,然后使用==is 而不是in 进行检查
【解决方案3】:

根据对您的问题和 cmets 的编辑,我想我(最终)了解您想要做什么,所以这是我经过大幅修改的答案。

我认为显示的代码可以进行一些改进/优化,但首先需要确认它现在正在做正确的事情。

import re

def func(comps):
    pats = [c for c in re.findall(r'\w\d+', comps)]

    for k, v in my_dict.items():
        if any(p in k for p in pats):
            return v

    return 0

# Testcases

my_dict = {'C99': 1, 'C4': 1}
components_list =  ['C99C2C3C5', 'C88C4']
result = [func(comps) for comps in components_list]
print('result:', result)  # -> result: [1, 1]

my_dict = {'C99': 1,'C15': 1}
components_list = ['C1C15C99', 'C15', 'C17']
result = [func(comps) for comps in components_list]
print('result:', result)  # -> result: [1, 1, 0]

my_dict = {'C1C55C99': 1, 'C17': 1, 'C3': 1}
components_list = ['C1C15C55C99', 'C15', 'C17']
result = [func(comps) for comps in components_list]
print('result:', result)  # -> result: [1, 0, 1]

注意:您真的不应该将变量命名为与 Python 内置函数相同的名称,例如 dict,因为它会造成混淆,并且可能会导致细微的错误,除非您非常小心(或刚刚得到幸运的)。

一般来说,我建议遵循PEP 8 - Style Guide for Python Code,尤其是Nnaming Conventions 部分,这还需要将ComponentList 更改为由"_" 字符分隔的小写单词——在这种情况下,components_list 将符合指南.

【讨论】:

  • 嗨,Martineau,假设我有一个字典和 my_dict = {'C1C55C99': 1, 'C17': 1, 'C3': 1}, component_list = ['C1C15C55C99 ', 'C15', 'C17'] 因为字典中的 'C1C5C99' 确实出现在 'C1C15C55C99' 中,它应该更改为字典值 1 但不会。希望你能帮忙。本
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2020-07-27
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2016-12-01
相关资源
最近更新 更多