需要帮助按键对对象列表进行排序

发布于 2024-09-08 05:12:32 字数 1696 浏览 8 评论 0原文

我无法让此代码使用 .sort() 或sorted() 对对象列表进行排序。我在这里缺少什么?

PS 如果有人有任何建议,我的解决方案.distance() 方法也可以使用一些整容手术。

谢谢!

import random
import math

POPULATION_SIZE = 100

data = [[1, 565.0, 575.0],
        [2, 25.0, 185.0],
        [3, 345.0, 750.0],
        [4, 945.0, 685.0],
        [5, 845.0, 655.0],
        [6, 880.0, 660.0],
        [7, 25.0, 230.0],
        [8, 525.0, 1000.0],
        [9, 580.0, 1175.0],
        [10, 650.0, 1130.0]
        ]

class Solution():

  def __init__(self):
    self.dna = []
    self.randomize()

  def randomize(self):
    temp = data[:]
    while len(temp) > 0:
      self.dna.append( temp.pop( random.randint( 0,len(temp)-1 ) ) ) 

  def distance(self): 
    total = 0 
    #There has to be a better way to access two adjacent elements.
    for i, points in enumerate(self.dna):
      if i < (len(self.dna)-1): 
        total += math.sqrt( (points[1]-self.dna[i+1][1])**2 + (points[2]-self.dna[i+1][2])**2 )
      else:
        total += math.sqrt( (points[1]-self.dna[0][1])**2 + (points[2]-self.dna[0][2])**2 )
    return int(total)


class Population():

  def __init__(self):
    self.solutions = []
    self.generation = 0

    #Populate with solutions
    self.solutions = [Solution() for i in range(POPULATION_SIZE)]


  def __str__(self):

    result = ''

    #This is the part that is not returning sorted results.  I tried sorted() too.
    self.solutions.sort(key=lambda solution: solution.distance, reverse=True)


    for solution in self.solutions:
      result += 'ID: %s - Distance: %s\n' % ( id(solution),  solution.distance() )

    return result


if __name__ == '__main__':

  p = Population()
  print p

I am unable to get this code to sort a list of objects using either .sort() or sorted(). What am I missing here?

P.S. My solution.distance() method could use some cosmetic surgery too if anyone has any suggestions.

Thanks!

import random
import math

POPULATION_SIZE = 100

data = [[1, 565.0, 575.0],
        [2, 25.0, 185.0],
        [3, 345.0, 750.0],
        [4, 945.0, 685.0],
        [5, 845.0, 655.0],
        [6, 880.0, 660.0],
        [7, 25.0, 230.0],
        [8, 525.0, 1000.0],
        [9, 580.0, 1175.0],
        [10, 650.0, 1130.0]
        ]

class Solution():

  def __init__(self):
    self.dna = []
    self.randomize()

  def randomize(self):
    temp = data[:]
    while len(temp) > 0:
      self.dna.append( temp.pop( random.randint( 0,len(temp)-1 ) ) ) 

  def distance(self): 
    total = 0 
    #There has to be a better way to access two adjacent elements.
    for i, points in enumerate(self.dna):
      if i < (len(self.dna)-1): 
        total += math.sqrt( (points[1]-self.dna[i+1][1])**2 + (points[2]-self.dna[i+1][2])**2 )
      else:
        total += math.sqrt( (points[1]-self.dna[0][1])**2 + (points[2]-self.dna[0][2])**2 )
    return int(total)


class Population():

  def __init__(self):
    self.solutions = []
    self.generation = 0

    #Populate with solutions
    self.solutions = [Solution() for i in range(POPULATION_SIZE)]


  def __str__(self):

    result = ''

    #This is the part that is not returning sorted results.  I tried sorted() too.
    self.solutions.sort(key=lambda solution: solution.distance, reverse=True)


    for solution in self.solutions:
      result += 'ID: %s - Distance: %s\n' % ( id(solution),  solution.distance() )

    return result


if __name__ == '__main__':

  p = Population()
  print p

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

江城子 2024-09-15 05:12:33

更改

key=lambda solution: solution.distance

key=lambda solution: solution.distance()

(调用该函数需要括号。)

或者,您可以将 distance 方法设为属性:

  @property
  def distance(self): 
      ....

在这种情况下,更改所有出现的 solution.distance()solution.distance。我认为这个替代解决方案更好一点,因为每次您想谈论距离时,它都会消除两个混乱的字符(括号)。

附言。 key=lambda 解决方案:solution.distanceself.solutions 中的每个 solution 返回绑定方法 solution.distance >。由于相同的对象作为每个解决方案的键返回,因此没有发生所需的排序。

Change

key=lambda solution: solution.distance

to

key=lambda solution: solution.distance()

(The parentheses are needed to call the function.)

Alternatively, you could make the distance method a property:

  @property
  def distance(self): 
      ....

In this case, change all occurances of solution.distance() to solution.distance. I think this alternate solution is a little bit nicer, since it removes two characters of clutter (the parens) every time you wish to talk about the distance.

PS. key=lambda solution: solution.distance was returning the bound method solution.distance for each solution in self.solutions. Since the same object was being returned as the key for each solution, no desired ordering occurred.

这是使用函数式编程技术清理类的尝试:

import random

class Solution():

  def __init__(self):
    self.dna = []
    self.randomize()

  def randomize(self):
    self.dna = data
    random.shuffle(self.dna)

  def distance(self):
    # Return the distance between two points.
    def point_distance((p1, p2)):
      return math.sqrt((p1[1]-p2[1])**2) + (p1[2]-p2[2])**2)
    # sums the distances between consecutive points.
    # zip pairs consecutive points together, wrapping around at end.
    return int(sum(map(point_distance, zip(self.dna, self.dna[1:]+self.dna[0:1])))

这未经测试,但应该接近工作。另外,建议使用类而不是数据的三元素列表。它将使您的代码更清晰易读:

   def point_distance((p1, p2)):
      return math.sqrt((p1.x-p2.x)**2) + (p1.y-p2.y)**2)

Here's an attempt at cleaning up your class, using functional programming techniques:

import random

class Solution():

  def __init__(self):
    self.dna = []
    self.randomize()

  def randomize(self):
    self.dna = data
    random.shuffle(self.dna)

  def distance(self):
    # Return the distance between two points.
    def point_distance((p1, p2)):
      return math.sqrt((p1[1]-p2[1])**2) + (p1[2]-p2[2])**2)
    # sums the distances between consecutive points.
    # zip pairs consecutive points together, wrapping around at end.
    return int(sum(map(point_distance, zip(self.dna, self.dna[1:]+self.dna[0:1])))

This is untested, but should be close to working. Also, a suggestion would be to use a class instead of a 3-element list for data. It will make your code much clearer to read:

   def point_distance((p1, p2)):
      return math.sqrt((p1.x-p2.x)**2) + (p1.y-p2.y)**2)
酒几许 2024-09-15 05:12:33

这是在 distance() 中编写循环的更好方法:放置以下函数定义,取自 itertools 文档,在你的代码中:

from itertools import izip, tee
def pairwise(iterable):
    a, b = tee(iterable)
    next(b, None)
    return izip(a, b)

然后你可以编写 distance 来利用 Python 高效的迭代器操作例程,如下所示:

from itertools import chain, islice
def distance(self): 
    all_pairs = islice(pairwise(chain(self.dna, self.dna)), 0, len(self.dna))
    return sum(math.sqrt((p[1]-q[1])**2 + (p[2]-q[2])**2) for p,q in all_pairs)

这应该是相当有效的,即使dna 数组非常长。

Here's a better way to write the loop in distance(): put the following function definition, taken from the itertools documentation, in your code:

from itertools import izip, tee
def pairwise(iterable):
    a, b = tee(iterable)
    next(b, None)
    return izip(a, b)

Then you can write distance to take advantage of Python's efficient iterator manipulation routines, like so:

from itertools import chain, islice
def distance(self): 
    all_pairs = islice(pairwise(chain(self.dna, self.dna)), 0, len(self.dna))
    return sum(math.sqrt((p[1]-q[1])**2 + (p[2]-q[2])**2) for p,q in all_pairs)

This should be reasonably efficient even if the dna array is very long.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文