获取具有最高 属性 的列表的 n 个元素

Get n elements of list having the highest property

我是 Haskell 的新手,正在尝试实现一些遗传算法。 目前我无法选择个人列表中的 n 个最佳元素(其中每个人都是自己的列表。 创建个人如下:

ind1 :: [Int]
ind1 = [1, 1, 1, 1, 1, 1, 1]
ind2 :: [Int]
ind2 = [0, 0, 0, 0, 0, 0, 0]

适当的人群包括这些个体的列表:

pop :: [[Int]]
pop = [ind1, ind2]

我想要实现的是获得种群中最好的n个个体,其中"best"由其元素的总和决定,例如

> sum ind1
7
> sum ind2
0

我开始创建一个函数来创建具有个体及其质量的元组:

f x = [(ind, sum ind) | ind <- x]

所以至少我得到了这样的东西:

[([1, 1, 1, 1, 1, 1, 1], 7), ([0, 0, 0, 0, 0, 0, 0], 0)]

如何从这里获得预期结果?我什至没有设法获得 "snd == max" 所在的元组的 "fst"。 我从不同主题中看到的递归方法开始,但不幸的是没有合理的结果。 任何建议,可能还有在哪里阅读? 谢谢!

使用sortBy and on.

> take 2 $ sortBy (flip compare `on` sum) [[1,2],[0,4],[1,1]]
[[0,4],[1,2]]

这里最好的选择是使用 sortBy from Data.List:

sortBy :: (a -> a -> Ordering) -> [a] -> [a]

sortBy 函数是高阶函数,因此它需要一个函数作为其参数之一。它需要的函数需要两个元素和 returns 一个 Ordering 值(LTEQGT)。您可以编写自己的自定义比较函数,但是 Data.Ord 模块有 comparing,它的存在是为了帮助编写这些比较函数:

comparing :: Ord b => (a -> b) -> (a -> a -> Ordering)

希望你能看到 comparing 如何与 sortBy 配对,你将一个函数传递给它以将你的类型转换为已知的可比较类型,然后你有一个正确类型的函数可以传递至 sortBy。所以在实践中你可以做

import Data.List (sortBy)
import Data.Ord (comparing)

-- Some types to make things more readable
type Individual = [Int]
type Fitness = Int

-- Here's our fitness function (change as needed)
fitness :: Individual -> Fitness
fitness = sum

-- Redefining so it can be used with `map`
f :: Individual -> (Individual, Fitness)
f ind = (ind, fitness ind)

-- If you do want to see the fitness of the top n individuals
solution1 :: Int -> [Individual] -> [(Individual, Fitness)]
solution1 n inds = take n $ sortBy (flip $ comparing snd) $ map f inds

-- If you just want the top n individuals
solution2 :: Int -> [Individual] -> [Individual]
solution2 n inds = take n $ sortBy (flip $ comparing fitness) inds

sortBy 参数中的 flip 强制排序为降序而不是默认的升序,因此从 sortBy 返回的第一个 n 值将是n 具有最高适应度的值按降序排列。如果你想尝试不同的健身功能,那么你可以做类似

的事情
fittestBy :: (Individual -> Fitness) -> Int -> [Individual] -> [Individual]
fittestBy fit n = take n . sortBy (flip $ comparing fit)

然后你会

solution2 = fittestBy sum

但你也可以

solution3 = fittestBy product

如果您想将适应度函数更改为乘积而不是总和。