代码之家  ›  专栏  ›  技术社区  ›  Bram Vanroy

在列表之间获取唯一的产品并维护输入顺序

  •  0
  • Bram Vanroy  · 技术社区  · 6 年前

    关于列表的唯一(笛卡尔)积,有很多问题,但我正在寻找一些我在其他任何问题中都没有发现的奇特的东西。

    我的输入将始终由两个列表组成。当列表相同时,我希望得到所有组合,但当它们不同时,我需要唯一的产品(即顺序无关紧要)。 然而 此外,我还需要保持秩序,在某种意义上说 输入 列出事项。事实上,我需要的是,第一个列表中的项目应该始终是产品元组的第一个项目。

    我有下面的工作代码,它满足了我的需要,但我没有找到一个好的、有效的方法来保持如上所述的项目顺序。

    import itertools
    
    xs = ['w']
    ys = ['a', 'b', 'c']
    
    def get_up(x_in, y_in):
        if x_in == y_in:
            return itertools.combinations(x_in, 2)
        else:
            ups = []
            for x in x_in:
                for y in y_in:
                  if x == y:
                      continue
                  # sort so that cases such as (a,b) (b,a) get filtered by set later on
                  ups.append(sorted((x, y)))
            ups = set(tuple(up) for up in ups)
            return ups
    
    print(list(get_up(xs, ys)))
    # [('c', 'w'), ('b', 'w'), ('a', 'w')]
    

    如您所见,结果是按字母顺序排列的唯一元组列表。我使用了排序,这样就可以使用集合来过滤重复的条目。但是因为第一个列表( xs )包含 w ,我想让元组有这个 W 作为第一项。

    [('w', 'c'), ('w', 'b'), ('w', 'a')]
    

    如果两个列表之间存在重叠,则两个列表中出现的项目顺序无关紧要。,所以对于 xs = ['w', 'a', 'b'] ys = ['a', 'b', 'c'] 订单 a 没关系

    [('w', 'c'), ('w', 'b'), ('w', 'a'), ('a', 'b'), ('a', 'c'), ('b', 'c')]
                                             ^
    

    [('w', 'c'), ('w', 'b'), ('w', 'a'), ('a', 'c'), ('b', 'a'), ('b', 'c')]
                                                         ^
    

    最好我会有一台发电机(如 combinations 返回)。我也只对Python感兴趣>=3.6。

    2 回复  |  直到 6 年前
        1
  •  0
  •   alexis    6 年前

    以保持顺序的方式收集元组(当列表相同时),然后通过移除逆元组进行过滤。

    if x_in == y_in:
            return itertools.combinations(x_in, 2) 
        else:
            seen = set()
            for a,b in itertools.product(x_in, y_in):
                if a == b or (b, a) in seen:
                    continue
                else:
                    yield (a,b)
                    seen.add((a,b))
    

    这将为您提供元组 (x, y) 顺序当两者都 (a,b) (b,a) 发生时,您只会获得首先看到的顺序。

        2
  •  0
  •   Bram Vanroy    6 年前

    我会回答我自己的问题,不过我打赌使用itertools或其他工具会有更好的解决方案。

    xs = ['c', 'b']
    ys = ['a', 'b', 'c']
    
    
    def get_unique_combinations(x_in, y_in):
        """ get unique combinations that maintain order, i.e. x is before y """
        yielded = set()
        for x in x_in:
            for y in y_in:
                if x == y or (x, y) in yielded or (y, x) in yielded:
                    continue
    
                yield x, y
                yielded.add((x, y))
    
        return None
    
    print(list(get_unique_combinations(xs, ys)))