将 2 个列表之间的数据排序到一个新列表中,并使用新列表中保存的数据设置字符串列表的格式

Sorting data between 2 lists into a new list, and formatting a list of strings using the data saved in the new list

提问人:Vic 提问时间:4/7/2023 最后编辑:Vic 更新时间:4/8/2023 访问量:49

问:

如果这不是很清楚,很抱歉,这是我第一次在这里问问题,所以我希望我能正确解释我的问题。

我有以下具有不同值的列表:

A_list = ['A', 'A', 'B', ['C', 'D'] ]
B_list = ['A1', 'W5', 'X6', 'A2', 'A3', 'T5', 'B0', 'Z9', 'C1', 'W3', 'D1']
C_list = []
string_list = ["{0} in Alpha", "{0} in Apple", "{0} in Bee", "{0} in Cheese and {1} in Dice"]

我需要在 B_list 中找到 A_list 的元素,将它们附加到 C_list,并让输出是来自 string_list 的格式化字符串,其中包含 C_list 中的元素。

所以在查找之后,结果会是这样的:A_list[i]B_listC_list

C_list = ['A1', 'A2', 'A3', 'B0', ['C1', 'D1'] ]

输出如下:

A1 in Alpha,
A1 in Apple,
A2 in Alpha,
A2 in Apple,
A3 in Alpha,
A3 in Apple,
B0 in Bee,
C1 in Cheese and D1 in Dice

我一直在用嵌套列表来破坏我的头脑,并以与A_list类似的顺序获取它们,以便能够使用如下内容格式化输出:

output = string_list[i].format(*C_list[i]) // just an example

我一直在尝试使用 for 循环和 if 语句的混合来解决这个问题。 我可以在一个简单的for循环中搜索in的元素:A_listB_list

for a in A_list:
    for b in B_list:
        if a in b:
            print(str(a) + " found in " + str(b))

让我崩溃的是如何将B_list中找到的元素添加到与A_list类似的格式中,以便我最终可以得到

C_list = ['A1', 'A2', 'A3', 'B0', ['C1', 'D1']]

而不是这个:

C_list = ['A1', 'A2', 'A3', 'B0', 'C1', 'D1']

python 排序 嵌套循环 字符串格式 嵌套列表

评论

0赞 mcursa-jwt 4/7/2023
嗨,应该只有一个吗?'A'A_list = ['A', 'A', 'B', ['C', 'D'] ]

答:

1赞 Samwise 4/7/2023 #1

如果在处理A_list时对其进行规范化,以便它始终是字符串列表,则问题将更容易管理:

for a in A_list:
    # Normalize a to a list[str]
    a = a if isinstance(a, list) else [a]
    # Pop all matches from B_list into C_list.
    while True:
        c = []
        for i in a:
            for b in B_list.copy():
                if b.startswith(i):
                    c.append(b)
                    B_list.remove(b)
                    break
            if len(c) == len(a):
                break  # append this c and scan B again
        else:
            break  # no more matches, continue to next a
        # Convert c back to a str|list[str]
        C_list.append(c[0] if len(c) == 1 else c)

print(C_list)
# ['A1', 'A2', 'A3', 'B0', ['C1', 'D1']]

我可能会建议在所有情况下都保留字符串列表,因为它可能会使您的格式化部分更容易,但希望上述内容能让您克服如何从这种棘手的嵌套格式中处理数据的初始障碍(同时仍然可以选择将其转换回原始棘手的格式如果需要)。c

评论

0赞 mcursa-jwt 4/8/2023
嘿,很好的答案,但是我意识到,如果有多个“C”,例如“C1”、“C2”、“C3”,你会得到.如何解决这个问题?['A1', 'A2', 'A3', 'B0', ['C1', 'C2']]
0赞 Samwise 4/8/2023
取决于你想从中得到什么输出。我必须根据您的示例推断规则,并且不清楚您将如何在该实例中应用它们。(注意:我不会根据更新的问题重写代码,只有第一个是免费的。
1赞 mcursa-jwt 4/8/2023 #2

第 1 部分:获得C_list

您必须自己创建嵌套列表以附加到C_list。 如果 A 中的项可以是字符串列表或字符串,则有 2 种情况。

def get_A_in_B(a_list:"list[str|list[str]]",b_list:"list[str]"):
    c_list = [] # global within this function     
    
    # for neatness   
    def process_base_item(a_str:"str",out_list:"list"):
        matches = sorted([b_str for b_str in b_list if b_str.startswith(a_str)])
        out_list.extend(matches)
    
    for a_item in a_list: # case 1 - is list, extend nested
        if type(a_item) is list:
            sublist = a_item
            nested_list = []
            for sub_item in sublist:
                process_base_item(sub_item,nested_list)
            if nested_list:
                c_list.append(nested_list)
        else: # case 2 - is string, extend c list
            process_base_item(a_item,c_list)
    return c_list

用法:

A_list = ['A', 'B', ['C', 'D'] ]
B_list = ['A1', 'W5', 'X6', 'A2', 'A3', 'T5', 'B0', 'Z9', 'C1', 'W3', 'D1']
C_list = get_A_in_B(A_list,B_list,string_list)

输出:

['A1', 'A2', 'A3', 'B0', ['C1', 'D1']]

第 2 部分:格式化

如果坚持 2 个假设,这将起作用:

  1. 假设格式字符串中每种类型的字母只有一个
  2. 假设如果嵌套不均匀,是否要循环所有可能性 例如 [“C1”, “C2”, “D1”] => “C1”+“D1”, “C2”+“D1”

这是真正棘手的部分。 我使用正则表达式将字母与格式字符串匹配。

对于嵌套列表,我按字母将它们拆分为更多的子列表,然后让它们的笛卡尔积作为多个参数输入到格式字符串中。C_list

和以前一样,你有 2 个案例。

def format_string_list(c_list,string_list):
    formatted_string_list = []
    for c_item in c_list:
        for fmt_str in string_list:
            if type(c_item) is list: # case 1 - is list, match multiple
                c_sublist = c_item
                # assumption 1: letters are unique
                first_letters = sorted(set([c_str[0] for c_str in c_sublist]))
                matched_letters = []
                for letter in first_letters:
                    pat = f" in {letter}"
                    if pat in fmt_str:
                        matched_letters.append(letter)
                        
                if first_letters==matched_letters: 
                    # get dictionary of lists, indexed by first letter
                    c_str_d = {}
                    for letter in first_letters:
                        c_str_d[letter] = [c_str for c_str in c_sublist if letter in c_str]
                    
                    # assumption 2: get all combinations
                    for c_str_list in itertools.product(*c_str_d.values()):
                        c_fmtted = fmt_str.format(*c_str_list)
                        formatted_string_list.append(c_fmtted) 
            else: # case 2
                c_str = c_item
                first_letter = c_str[0]
                pat = f" in {first_letter}"

                if pat in fmt_str:
                    c_fmtted = fmt_str.format(c_str)
                    formatted_string_list.append(c_fmtted)
    
    return formatted_string_list

用法:

C_list = ['A1', 'A2', 'A3', 'B0', ['C1', 'D1'] ]
string_list = ["{0} in Alpha", "{0} in Apple", "{0} in Bee", "{0} in Cheese and {1} in Dice"]
formatted_string_list = format_string_list(C_list,string_list)
# print output
print("\n".join(formatted_string_list))

输出:

A1 in Alpha
A1 in Apple
A2 in Alpha
A2 in Apple
A3 in Alpha
A3 in Apple
B0 in Bee
C1 in Cheese and D1 in Dice

也适用于更复杂的情况

不会超过一个级别的嵌套,不要认为你的情况需要它

A_list = ['A', 'B', ['C', 'D', 'E']]
B_list = ['A1', 'W5', 'X6', 'D2', 'E1', 'A2', 'A3', 'T5', 'E2', 'B0', 'Z9', 'C1', 'W3', 'D1']
string_list = ["{0} in Alpha", "{0} in Apple", "{0} in Bee", "{0} in Cheese and {1} in Dice {2} in Egg"]

输出:

['A1', 'A2', 'A3', 'B0', ['C1', 'D1', 'D2', 'E1', 'E2']]
A1 in Alpha
A1 in Apple
A2 in Alpha
A2 in Apple
A3 in Alpha
A3 in Apple
B0 in Bee
C1 in Cheese and D1 in Dice E1 in Egg
C1 in Cheese and D1 in Dice E2 in Egg
C1 in Cheese and D2 in Dice E1 in Egg
C1 in Cheese and D2 in Dice E2 in Egg