【问题标题】:Tuple to Set as coordinates设置为坐标的元组
【发布时间】:2019-05-09 16:57:43
【问题描述】:

我有一个元组,它给了我这样的东西:

(array([115, 115, 295], dtype=int64), array([377, 378,404], dtype=int64))

现在我想把它转换成这样的集合:

{(115,377),(115,378),(295,404)}

我目前正在使用这种方法:

def edges2cordinate(edges):
    l = int(len(edges[0]))
    res=set()
    for i in range (0,len):
        res.add((edges[0][i],edges[1][i]))
    return res

Code link

但是给了我错误。

Traceback(最近一次通话最后一次): 文件“F:\canny_vertices.py”,第 40 行,在 print(edges2cordinate(indices)) 文件“F:\canny_vertices.py”,第 16 行,在 edge2cordinate 中,i 在范围 (0,len) 中: TypeError: 'builtin_function_or_method' 对象不能被解释为整数

我错过了什么?

【问题讨论】:

  • 没有代码链接,请将您的整个代码粘贴到这里!
  • 您使用的是哪个 python 版本。 2个还是3个?不要同时标记它们。
  • 代码已添加,请再看
  • 我有 2.7 的台式机和 3 的笔记本电脑,所以我都需要:p
  • 你的意思是使用 l 而不是 len 作为范围?

标签: python


【解决方案1】:

在您之前的代码中,您可能希望使用range (0,l) 而不是range (0,len),因为您已将长度变量保存在l 中,因此您希望将该长度传递给range 变量而不是内置变量函数len

一旦你这样做了,原始代码就可以正常工作了


def edges2cordinate(edges):
    l = int(len(edges[0]))
    res=set()
    for i in range (0,l):
        res.add((edges[0][i],edges[1][i]))
    return res

print(edges2cordinate([[115, 115, 295],[377, 378,404]]))

输出将是{(295, 404), (115, 378), (115, 377)}

但这也可以通过zip 轻松完成,我们解压缩列表列表,将其作为参数传递给zip,然后将压缩迭代器转换回set,注意我们看到一个由于set

,此处输出无序
li = [[115, 115, 295],[377, 378,404]]

print(set(zip(*li)))

输出将是{(295, 404), (115, 378), (115, 377)}

要反转项目,只需在通过列表理解创建集合时通过反转元组的各个元素来反转它们!

li = [[115, 115, 295],[377, 378,404]]

print(set((y,x) for x, y in zip(*li)))

输出将是{(404, 295), (377, 115), (378, 115)}

【讨论】:

  • 鉴于 OP 错误地将 len 函数传递给范围,也许您应该考虑不只是给他们一个他们可能甚至不会理解或至少解释他们的内容的单行做错了,你的解决方案是如何工作的
  • 已修复 @juanpa.arrivillaga 请看一下是否看起来更好:)
  • 我怎样才能把它们中的每一个都颠倒过来,比如从(295, 404)(404, 295)
【解决方案2】:

使用zip解包:

list(zip(*tupl))  # where tupl is your tuple

它会输出一个与您的期望相反的值列表。但我想这可能更合适,因为 set 会删除重复项并且没有顺序。

【讨论】:

    【解决方案3】:
    def edges2cordinate(edges):
        res = set()
        for i in range(len(edges[0])):
            res.add((edges[0][i], edges[1][i]))
        return res
    
    edge = ([115, 123, 295], [377, 378, 404])
    res = edges2cordinate(edge)
    set(reversed(list(res)))
    

    这也给出了正确的输出{(115, 377), (115, 378), (295, 404)},如果您不熟悉zip,这是一个更简单的解决方案。上面正确回答了您的代码无法正常工作的原因。

    【讨论】:

      【解决方案4】:

      为了解释如何获得所有其他答案,我们从 OPs 原始代码的整理(和固定)版本开始:

      def edges2cordinate(edges):
          num_entries = len(edges[0])
          res = set()
          for i in range(0, num_entries):
              res.add((edges[0][i], edges[1][i]))
          return res
      

      第一次清理发生在注意到range() 允许传递单个参数之后,导致它从零计数到该参数。我们还注意到num_entries 只使用了一次,所以我们可以将它移动到使用它的位置,给我们:

      def edges2cordinate(edges):
          res = set()
          for i in range(len(edges[0])):
              res.add((edges[0][i], edges[1][i]))
          return res
      

      其次,请注意,在for 循环的每次迭代中,我们都会不断获取edges 的第一个和第二个元素。 Python 为我们提供了“assignment expressions”(PEP 572),这让我们可以这样写:

      def edges2cordinate(edges):
          first_arr, second_arr = edges
          res = set()
          for i in range(len(first)):
              res.add((first_arr[i], second_arr[i]))
          return res
      

      而且应该会快一点,因为我们只需要将项目取出一次,而不是每次循环迭代。

      每个答案都指向使用zip() 使这段代码更简洁。你使用zip 给它多个可以迭代的东西,比如lists 或你的数组,然后它会压缩它们,给你返回包含你给它的东西中的项目的元组。例如:

      list(zip([1,2,3], [4,5,6]))
      

      计算为[(1,4), (2,5), (3,6)]list() 包围它的原因是(在 Python 3 中)zip 给你一个迭代器,并将这个迭代器传递给 list() 给你一个包含来自该迭代器的项目的列表。

      第三,在上述代码中使用zip 的最小变化是:

      def edges2cordinate(edges):
          first_arr, second_arr = edges
          res = set()
          for first_item_i, second_item_i in zip(first_arr, second_arr):
              res.add((first_item_i, second_item_i))
          return res
      

      此外,我们正在使用这些“赋值表达式”来冗余地将它们分开并将它们组合在一起,因此我们可以将其重写为:

      def edges2cordinate(edges):
          res = set()
          for pair_i in zip(edges[0], edges[1]):
              res.add(pair_i)
          return res
      

      我们也可以改为使用zip(*edges),其中“unpacksedges 成为zip 的参数,即edges[0] 转到zip 的第一个参数,edges[1] 转到第二个参数等

      Python 为您提供的另一个工具是generator expressions,它可以让我们将很多内容变成一行:

      def edges2cordinate(edges):
          return set(pair_i for pair_i in zip(*edges))
      

      但我们并没有对这个生成器表达式“做任何事情”,所以可以将其删除,达到极简主义:

      def edges2cordinate(edges):
          return set(zip(*edges))
      

      在后续评论中,您询问了如何反转边缘的顺序。一种方法是:

      def edges2cordinate(edges):
          return set(zip(edges[1], edges[0]))
      

      这有望做显而易见的事情。建议的 reversed() 函数可能符合您的预期,但可以用作:

      def edges2cordinate(edges):
          return set(zip(*reversed(edges)))
      

      尽量减少

      【讨论】:

        猜你喜欢
        • 2013-05-20
        • 1970-01-01
        • 1970-01-01
        • 2016-04-17
        • 2012-11-06
        • 1970-01-01
        • 2011-11-13
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多