使用sortBy对列表进行排序 [英] sorting lists using sortBy

查看:759
本文介绍了使用sortBy对列表进行排序的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在尝试根据每个元组中的第4个元素对元组列表进行排序.第四个元素包含一个字符串,该字符串是一个人的名字.我想将包含相同名称的元组彼此相邻.在对元组进行排序之前,其列表的示例为:

[("A",100,"Q",3,"Todd",2.0),
 ("B",203,"R",3,"Rachel",1.66),
 ("B",273,"F",1,"Mike",2.66),
 ("A",200,"P",1,"Rachel",0.0),
 ("A",549,"D",3,"Todd",2.0),
 ("B",220,"S",3,"Todd",4.0),
 ("B",101,"M",3,"Jon",3.33),
 ("A",999,"N",3,"Rachel",1.33)]

我也希望它看起来像这样:

[("A",100,"Q",3,"Todd",2.0),
 ("A",549,"D",3,"Todd",2.0),
 ("B",220,"S",3,"Todd",4.0),
 ("B",203,"R",3,"Rachel",1.66),
 ("A",200,"P",1,"Rachel",0.0),
 ("A",999,"N",3,"Rachel",1.33),
 ("B",273,"F",1,"Mike",2.66),
 ("B",101,"M",3,"Jon",3.33)]

我需要的是将包含Todd的所有元组彼此相邻,以此类推.名称显示的顺序无关紧要,只要它们彼此相邻即可.

sortedList= show . sortBy byName . (map stringToTuple) . (map words) . lines

这是我在其中排序的代码行.我知道我需要创建一个函数byName,它将以某种方式弄清楚元组是否具有通用名称.

任何帮助引导我朝正确方向编写byName方法的帮助. 谢谢

解决方案

sortBy类型开始:

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

这意味着byName需要具有类型a -> a -> Ordering.在这种情况下,a是一个元组,其第五个元素为类型StringbyName将忽略其他字段.因此,您需要定义一个函数,如

type MyType = (String, Int, String, Int, String, Double)
byName :: MyType -> MyType -> Ordering
byName (_, _, _, _, a, _) (_, _, _, _, b, _) = ...

我将使用正确的表达式替换...作为练习.

(回想一下Ordering是具有三个值LTEQGT的类型,其中byName a b == LT如果a < bbyName a b == EQ如果a == bbyName a b == GT如果是a > b.在您的情况下,只要它们具有相同的名称,两个元组就会进行比较.听起来好像您实际上并不在乎byName返回LT还是GT.)

I am trying to sort my list of tuples based on the 4th element in each of the tuples. The fourth element contains a string that is a person's name. I want to put tuples that contain the same name next to each other. An example of the lists of tuples before it is sorted is:

[("A",100,"Q",3,"Todd",2.0),
 ("B",203,"R",3,"Rachel",1.66),
 ("B",273,"F",1,"Mike",2.66),
 ("A",200,"P",1,"Rachel",0.0),
 ("A",549,"D",3,"Todd",2.0),
 ("B",220,"S",3,"Todd",4.0),
 ("B",101,"M",3,"Jon",3.33),
 ("A",999,"N",3,"Rachel",1.33)]

I want it too look like:

[("A",100,"Q",3,"Todd",2.0),
 ("A",549,"D",3,"Todd",2.0),
 ("B",220,"S",3,"Todd",4.0),
 ("B",203,"R",3,"Rachel",1.66),
 ("A",200,"P",1,"Rachel",0.0),
 ("A",999,"N",3,"Rachel",1.33),
 ("B",273,"F",1,"Mike",2.66),
 ("B",101,"M",3,"Jon",3.33)]

What I need is for all the tuples that contain Todd to be next to each other and so on for each name. The order the names show up doesn't matter, just that they are next to each other.

sortedList= show . sortBy byName . (map stringToTuple) . (map words) . lines

This is the line of code I am calling sort by in. I understand I need to make a function byName that will somehow figure out if the tuples share a common name.

Any help to steer me into the right direction for writing the byName method would be appreciated. Thank you

解决方案

Start with the type of sortBy:

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

This means byName needs to have type a -> a -> Ordering. In this case, a is a tuple whose fifth element as type String; byName will ignore the other fields. So you'll need to define a function like

type MyType = (String, Int, String, Int, String, Double)
byName :: MyType -> MyType -> Ordering
byName (_, _, _, _, a, _) (_, _, _, _, b, _) = ...

I leave replacing the ... with the correct expression as an exercise.

(Recall that Ordering is a type with three values, LT, EQ, and GT, where byName a b == LT if a < b, byName a b == EQ if a == b, and byName a b == GT if a > b. In your case, two tuples will compare as equal as long as they have the same name. It sounds like you don't actually care whether byName returns LT or GT otherwise.)

这篇关于使用sortBy对列表进行排序的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆