【问题标题】:Selecting from a tuples of list从列表元组中选择
【发布时间】:2015-10-17 20:20:43
【问题描述】:

我有一个名称对的元组列表,每对都有一个值,格式如下:

1.[('Carlo', 'Helen', 9), ('Carlo', 'Mary', 4), ('Jan', 'Rolly', 1), ('Renzi', 'Rolly', 3)] 
2.[('Sofy', 'Reem', 9), ('Sofy', 'David', 5),('Sofy', 'keem', 3) ('Roly', 'Tony', 4), ('Gianni', 'Tony', 2)]
3.[('Sofy', 'Reem', 9), ('Sofy', 'David', 5),('Sofy', 'keem', 3),('Roly', 'Reem', 5), ('Roly', 'David', 2),('Roly', 'keem', 3)]

我想要的是:对于列表中的每一行,如果两对或多对名称共享一个名称(第一个或第二个名称),我必须选择具有高价值的对。所以对于上面的例子,输出将是

  1-('Carlo', 'Helen', 9) 
    ('Renzi', 'Rolly', 3)
  2-('Sofy', 'Reem', 9)
    ('Roly', 'Tony', 4)

有人可以帮忙吗?

【问题讨论】:

  • 只是为了澄清。这个问题来自here
  • ('Jan', 'Rolly', 1)('Gianni', 'Tony', 2) 怎么样?
  • ('Jan', 'Rolly', 1) 和 ('Gianni', 'Tony', 2) 将不被考虑,因为与共享它们的对相比,它们的价值较低一个名字但有很高的价值

标签: python python-2.7 python-3.x


【解决方案1】:

我还没有找到改进的方法,但是您可以对您的列表进行两次检查。在外循环中,每个项目都被选为候选对象。在内部循环中,每个在姓名或姓氏上匹配并替换候选者进行选择的iteam当且仅当其分数高于当前候选者时。在内部循环结束时,如果尚未插入候选人,则将其插入选择列表。

def get_top_scorers(dataset):
    if dataset and all(isinstance(d, list) for d in dataset):
        return [get_top_scorers(d) for d in dataset]
    selected_list = []
    for candidate in dataset:
        chosen = candidate
        for next_candidate in dataset:
            if next_candidate == chosen:
                continue
            next_name, next_surname, next_score = next_candidate

            shares_name_with_selected = any(
                next_name == s[0] or next_surname == s[1]
                for s in selected_list
            )
            if shares_name_with_selected:
                continue

            name, surname, score = chosen
            if (name == next_name or surname == next_surname) and score < next_score:
                chosen = next_candidate

        shares_name_with_selected = any(
            chosen[0] == s[0] or chosen[1] == s[1]
            for s in selected_list
        )
        if chosen not in selected_list and not shares_name_with_selected:
            selected_list.append(chosen)
    return selected_list

【讨论】:

  • 你的答案很合适,但是这个case没有得到:[('Sofy', 'Reem', 9), ('Sofy', 'David', 5),('Sofy' , 'keem', 3), ('Roly', 'Reem', 4), ('Roly', 'David', 2), ('Roly', 'keem', 1)]。使用您的代码,这里的输出是: [('Sofy', 'Reem', 9), ('Sofy', 'David', 5), ('Sofy', 'keem', 3)]
  • 这对是最后一种情况所需的输出:('Sofy', 'Reem', 9), ('Roly', 'Reem', 4)
  • 但是您的示例输出共享“Reem”,这不是您想要的。
  • 输出对可以共享项目
  • 你在你的问题中说:“如果两对或多对名字共享一个名字(第一个或第二个名字)我必须选择高价值的对”这意味着没有一对可以共享名字或名字。无论如何,我已经更改了代码以准确反映您的要求。
【解决方案2】:

你需要两个函数。一种是迭代分组,另一种是寻找最高值:

def find_highest_pair(tuple):
    highest_value = 0
    result = []
    for pair in tuple:
        if pair[2] > highest_value:
            highest_value = pair[2]
            result = pair
    return result

def grouping(tuple,n):
    stack = []
    result = []
    backup = []
    if tuple:
        check_pair = tuple.pop(0)
        backup = tuple
        if tuple:
            if check_pair[n] == tuple[0][n]:
                stack.append(tuple[0])
                tuple.pop(0)
        if not stack and len(tuple) > 0:
            return grouping(backup,n)
    stack.append(check_pair)
    result = find_highest_pair(stack)
    return result


tuple1 = [('Carlo', 'Helen', 9), ('Carlo', 'Mary', 4), ('Jan', 'Rolly', 1), ('Renzi', 'Rolly', 3)]
tuple2 = [('Sofy', 'Reem', 9), ('Sofy', 'David', 5), ('Sofy', 'keem', 3), ('Roly', 'Tony', 4), ('Gianni', 'Tony', 2)]

print "1:"
print grouping(tuple1,0)
print grouping(tuple1,1)
print "2:"
print grouping(tuple2,0)
print grouping(tuple2,1)

【讨论】:

  • print find_highest_pair(tuple1) 给出了输出 ('Carlo', 'Helen', 9),但是需要的输出是 ('Carlo', 'Helen', 9) ('Renzi', '罗利',3)
  • @user3573552 ('Renzi', 'Rolly', 3) 不是最低的。你选择这个元素的标准是什么?不是最低,也不是最高,那又如何?
  • 需要的不仅是列表中的最高值,而且只有同名的对之间的最高值
  • @user3573552 OK 等待。
【解决方案3】:
 # this contains both lists
lt = [('Carlo', 'Helen', 9), ('Carlo', 'Mary', 4), ('Jan', 'Rolly', 1), ('Renzi', 'Rolly', 3),
                      ('Sofy', 'Reem', 9), ('Sofy', 'David', 5),('Sofy', 'keem', 3), ('Roly', 'Tony', 4), ('Gianni', 'Tony', 2)]

           def max_value_tuples(tuple_list):
            # find max value tuples in the list of tuple
            import itertools as it
            import operator as op
            groups = []

            # group by first element
            for k, g in it.groupby(tuple_list, key=op.itemgetter(0)):
                groups.append(list(g))
            # group by second element
            for k, g in it.groupby(tuple_list, key=op.itemgetter(1)):
                groups.append(list(g))

            final = []
            # leave out idividiual tuples
            for el in groups:
                if len(el) > 1:
                    final.append(el)

            result = []
            # sort and print with highest scrores
            for el in final:
                el = sorted(el, key=op.itemgetter(2))
                result.append(el[-1])

            return result

        print(max_value_tuples(lt))

        [('Carlo', 'Helen', 9), ('Sofy', 'Reem', 9), ('Renzi', 'Rolly', 3), ('Roly', 'Tony', 4)]

    with this and your astfile, you could do:

    all_lists = []
    for x in astfile:
        x_list = max_value_tuples(x)
        all_lists.append(x_list)

【讨论】:

  • 如果它的格式为:[[('Carlo', 'Helen', 9), ('Carlo', 'Mary', 4), ('Jan', 'Rolly', 1) ] [('Carlo', 'Helen', 9), ('Carlo', 'Mary', 4), ('Jan', 'Rolly', 1) ]]?
  • @user3573552 我刚刚更新了。看一看。它是元组列表。与原始列表的格式相同。
  • 在我的情况下,它的文件是一个元组列表,所以我使用 ast。所以我必须使用: For x in ast(file): x.这里 x 在您的代码中等于 a It。如何将 ast(file): x 中的循环 For x 与您的代码结合起来?
  • @user3573552 如果每个 x 在我的代码中都是 lt,并且您需要处理整个文件,则必须将我的脚本放入函数 f 并在 ast(file) 中使用类似 for x 的东西: f(x)。如果你愿意,我可以从脚本中创建一个函数。
  • 能否将此函数与您的代码结合起来
【解决方案4】:

这行得通:

def fix_list(list_name):
    delete_list = []
    for i in range(len(list_name)):
        for j in range(len(list_name[i])):
            for k in range(1,len(list_name)):
                if i == k:
                    pass
                else:
                    if list_name[i][j] == list_name[k][j]:
                        if list_name[i][2] >= list_name[k][2]:
                            delete_list.append(list_name[k])
    list_name = [item for item in list_name if item not in delete_list]
    print list_name

    #Use return instead of print if you want to assign the new list to something

fix_list(list1)
fix_list(list2)

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2021-12-28
    • 2011-12-14
    • 1970-01-01
    • 2011-03-28
    • 2014-03-10
    • 2011-10-01
    • 1970-01-01
    • 2023-01-11
    相关资源
    最近更新 更多