【问题标题】:Custom sorting in for loopfor循环中的自定义排序
【发布时间】:2013-12-16 05:19:42
【问题描述】:

假设给定一个包含 n 个点(坐标对)的数组。我想生成一个二维点数组,其中 ith 行的所有元素都根据它们与 ith 点的距离进行排序。可能有更好和更有效的算法来获得最终结果,但出于某些原因,我想通过 naive 算法来做到这一点,即蛮力。我也不想编写自己的排序函数。

在 C 语言中,可以使用 qsort 函数,但它的比较函数只需要两个参数,而我需要传递三个参数:参考点和其他两个要比较的点。

在 Python 中也可以使用sorted 函数,但同样,它的关键函数只需要一个参数,而在这种情况下,我需要传递两个参数。

那我该怎么做呢?

【问题讨论】:

  • 您的设置中的“行”是什么?
  • 肮脏的解决方案:将参考点作为全局变量传递。
  • 在二维数组中,第 i 行包含所有 n 个点,根据它们与点 a_i 的距离排序,其中 a_i 是输入的一维数组中的第 i 个点。
  • @chux: 是的,应该可以的

标签: python c arrays algorithm sorting


【解决方案1】:

也许使用嵌套的 for 循环,外部循环查看第 i 个点。然后在循环内计算所有距离。计算后对该行使用原生 python 排序,然后将其添加到主二维数组。

【讨论】:

    【解决方案2】:

    您可以定义一个函数来获取相关信息(参考,两个点)并将其映射到距离:

    def deteremineDistance(reference, pt1, pt2):
        #determine distances according to your definition and store it in variable "dist"
        return dist
    

    然后可以对该函数的结果进行排序,同时跟踪它们与实际数据的对应关系。

    【讨论】:

      【解决方案3】:

      您可以定义一个函数制作函数来为每个点创建一个自定义的距离函数。

      pts = [(1,1), (3,4), (1,8), (7,6)]
      
      def mk_distsq(a):
          def distsq(b):
              return ((b[0]-a[0])**2 + (b[1]-a[1])**2)**0.5
          return distsq
      
      dist = [sorted(pts, key=mk_distsq(pt)) for pt in pts]
      

      【讨论】:

      • 或者,只需编写一个常规距离函数(或平方距离,它给出相同的排序顺序)并使用functools.partial 来修复其中一个参数。
      【解决方案4】:
      grid = [sorted(l, key=lambda x: distance(x, y)) for y in l]
      

      Lambda 可以是闭包。但是,这很容易出错,因为当y 的值在下一次迭代中发生变化时,所有的 lambdas 都会开始使用新值。我相信这不会影响这段代码,但我会觉得使用functools.partial 会更安全:

      grid = [sorted(l, key=functools.partial(distance, x)) for x in l]
      

      【讨论】:

      • y 的值变化不会使 lambda 容易出错 - 事实上,您的 partial 示例依赖于相同的行为(x 每次迭代都会发生变化,并且所有partials 开始使用新值)。
      • @lvc:不!旧的partial 对象(如果它们还在的话)仍将使用它们原来的x 值。该参数在创建 partial 对象时绑定。
      【解决方案5】:

      对于帖子的 C 部分:
      使用全局变量。应该没问题,除了不是多线程安全的。

      假设 OP 具​​有比较功能来比较 2 点与参考点的距离:

      int compare(const pt *a, const pt2 *b, const pt2 *ref);
      

      添加

      static const pt2 *local_ref;
      
      static int local_compare(pt **a, pt2 **b) {
        return compare(*a, *b, local_ref);
      }
      
      void qsort_list(pt2 *list[], size_t n, pt2 *ref) {
        local_ref = ref;
        qsort(list,  n, size(*list), local_compare);
      }
      

      【讨论】:

        【解决方案6】:

        假设坐标列表绑定到pairs。那么这里有一个 1-statement 的方式:

        [sorted(pairs,
                key=lambda point: (point[0] - ref[0])**2 + (point[1] - ref[1])**2)
         for ref in pairs]
        

        例如,给定:

        pairs = [(1, 2), (2, 3), (3, 4), (4, 5)]
        

        产生:

        [[(1, 2), (2, 3), (3, 4), (4, 5)],
         [(2, 3), (1, 2), (3, 4), (4, 5)],
         [(3, 4), (2, 3), (4, 5), (1, 2)],
         [(4, 5), (3, 4), (2, 3), (1, 2)]]
        

        请注意,除非您需要实际距离,否则无需提取平方根。出于排序目的,您可以通过查看距离的平方得到相同的顺序。

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2011-11-27
          • 2022-01-07
          • 2020-01-23
          • 1970-01-01
          相关资源
          最近更新 更多