简体   繁体   English

Haskell - 删除元组列表中的 n 个最小元素

[英]Haskell - Remove n smallest elements in a list of tuples

I've got the following code that takes an int value and removes the first n amount of elements in a list.我有以下代码,它采用 int 值并删除列表中的前 n 个元素。

removeEle :: Int -> [a] -> [a]
removeEle n xs
    | ((n <= 0) || null xs) = xs
    | otherwise = removeEle (n-1) (tail xs)

How would i append this so that this works on a list of tuples by their second element?我将如何 append 这样才能按第二个元素对元组列表起作用? etc ETC

[(String1, 50)], [(String2, 600)], [(String3, 10)]

There is not much you can do to amend your current solution so that it removes the first n smallest elements.您无法修改当前解决方案以删除前n最小元素。 To be able to remove the first n smallest, you need to have the total ordering of the whole list so that you can decide which elements are in the n smallest interval.为了能够删除前n最小的,您需要对整个列表进行总排序,以便您可以决定哪些元素在n最小的区间内。

One easy solution is to sort the list and the remove the first n elements.一个简单的解决方案是对列表进行排序并删除前n元素。 This solution doesn't preserve the original ordering though.但是,此解决方案不会保留原始顺序。

Using soryBy and drop from Data.List you can do the following:使用soryBy并从Data.Listdrop ,您可以执行以下操作:

removeNSmallest :: Ord a => Int -> [(String, a)] -> [(String, a)]
removeNSmallest n xs = drop n $ sortBy (\(_, a) (_, b) -> compare a b) xs

As @Micha Wiedenmann pointed out, you can use sortBy (comparing snd) for sorting the tuples.正如@Micha Wiedenmann 指出的那样,您可以使用sortBy (比较 snd)对元组进行排序。

A small test:一个小测试:

λ> removeNSmallest 1 [("String1", 50), ("String2", 600), ("String3", 10)]
[("String1",50),("String2",600)]

To preserve the original ordering, one solution is to create a separate ordered list of the second elements of the tuple.为了保留原始顺序,一种解决方案是为元组的第二个元素创建一个单独的有序列表。 Then traverse the original list and for each element that is in the ordered list, remove one from the original.然后遍历原始列表,对于有序列表中的每个元素,从原始列表中删除一个。

Your original solution for removing the first n elements of a list would be much more readable if you wrote it using drop :如果您使用drop编写它,则删除列表的前 n 个元素的原始解决方案将更具可读性:

removeEle :: Int -> [a] -> [a]
removeEle n xs = drop n xs

Or if you want to use explicit recursion:或者,如果您想使用显式递归:

removeEle :: Int -> [a] -> [a]
removeEle _ [] = []
removeEle 0 xs = xs
removeEle n x:xs = removeEle (n-1) xs

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM