获取具有最高 属性 的列表的 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"。
我从不同主题中看到的递归方法开始,但不幸的是没有合理的结果。
任何建议,可能还有在哪里阅读?
谢谢!
> 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
值(LT
、EQ
或 GT
)。您可以编写自己的自定义比较函数,但是 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
如果您想将适应度函数更改为乘积而不是总和。
我是 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"。 我从不同主题中看到的递归方法开始,但不幸的是没有合理的结果。 任何建议,可能还有在哪里阅读? 谢谢!
> 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
值(LT
、EQ
或 GT
)。您可以编写自己的自定义比较函数,但是 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
如果您想将适应度函数更改为乘积而不是总和。