【问题标题】:haskell: convert one member of a list of lists from char to inthaskell:将列表列表的一个成员从 char 转换为 int
【发布时间】:2012-02-05 10:20:11
【问题描述】:

假设我有一个这样的列表:

list= [["a","123","b"],["h","435","t"],["w","234","j"]]

我需要将该列表列表的第二个成员转换为Integer,因为之后它将用作大小指示器,以便我可以按大小对列表进行排序。

我想出了一个转换函数:

charToInt c = ord (chr c)

但我不知道如何转换列表中的每个第二个成员。

【问题讨论】:

  • 你想在这里实现什么?内部列表的统一性使它看起来像是某种伪装的结构。您想按第二个元素的长度进行排序的事实使这看起来更有可能。所以我想知道您是否将这些列表视为一种动态类型的结构?
  • 嘿,保罗,我想要实现的是一个程序,它将在列表列表中为我提供一些文件的所有元数据,例如:list=[["music_A","size_A","artist_A",...],["music_B","size_B","artist_B",...]...] 所有元数据都来自@ 987654325@ 之后我想给用户按大小对所有数据进行排序的机会,我需要将大小转换为Int
  • 正如我所怀疑的,您正在尝试使用列表作为数据结构。这是一个坏主意。您需要创建一个数据结构来使用原生类型(例如 Integer 的大小)来保存您的数据,然后定义一个函数,例如 mkMetaData :: [String] -> MetaData。那么您可以拥有该数据类型的列表并按您喜欢的方式对其进行排序。
  • 我明白你的意思,我会试试看,谢谢。

标签: list haskell char int


【解决方案1】:

要扩展 Paul Johnson 所说的内容,您需要为要保存的数据定义数据类型。

data MusicFile = MusicFile {music :: String,
                            size :: Integer,
                            artist :: String}
    deriving Show

musicFileFromStrings :: [String] -> MusicFile
musicFileFromStrings [sMusic, sSize, sArtist]
   = MusicFile sMusic (read sSize) sArtist

如果你有

list = [["a","123","b"],["h","435","t"],["w","234","j"]]

你可以说

anotherList = map musicFileFromStrings list

然后

map music anotherList   -- ["a", "h", "w"]
map artist anotherList  -- ["b", "t", "j"]

(编辑)

如果您想按特定字段对列表进行排序,您可以使用“sortBy”和“comparing”。

import Data.List
import Data.Ord

sizeOrderList = sortBy (comparing size) anotherList

“比较”函数将一个值(在本例中为“大小”)的函数转换为两个值之间的比较函数。唯一的要求是“size”的输出(在这种情况下)是“Ord”实例的类型。

如果你想要降序而不是使用

sizeOrderList = sortBy (comparing (flip size)) anotherList

【讨论】:

  • 嘿伙计,感谢您的帮助。我已经按照您所说的进行了操作,但是当我尝试运行 anotherList 时出现此错误:No instance for (Show MusicFile) arising from a use of print' 可能的解决方法:在交互式 GHCi 命令的 stmt 中为 (Show MusicFile) 添加实例声明:打印它`
  • 好的,我只需添加 deriving Show 就可以正常工作,但现在我遇到了同样的问题,而不是 [["ad",23,"fd"],["g",54,"gs"],["yt",67,"fh"]],我有这个:[MusicFile {music = "ad", size = 23, artist = "fd"},MusicFile {music = "g", size = 54, artist = "gs"},MusicFile {music = "yt", size = 67, artist = "fh"}]
  • 查看我的编辑。您需要有关如何在 Haskell 中使用记录的教程吗?
  • 我想你不明白我的意思,你刚刚创建了两个包含所有音乐和所有艺术家的列表,但我不想这样,我想要一个文件中的所有元数据,因为稍后我必须将该信息转换为 pdf,以便用户可以在屏幕上看到每个文件的所有信息。
  • 所以现在你需要定义一个为每条记录生成文本的 prettyprint 函数。您可以使用“sortBy”和“comparing”将列表随机排列成您想要的任何顺序。例如。 "sortBy (comparing sSize) listOfMusic" 会做你想做的。
【解决方案2】:

如果不将类型从列表更改为类似元组的类型,则无法将内部列表的第二个元素转换为 Integer。原因是 Haskell 中的列表是同质的,所以需要一个元组来表示混合类型。

String 转换为Integer 是这样完成的:

read "123" :: Integer

您需要直接添加类型,因为read 的类型是Read a => String -> a,这意味着它将返回可以“读取”的类型。幸运的是,Integer 是该类型类的成员,因此我们可以将 String 转换为 Integer

现在只需转换每个内部列表的第二个元素即可:

convert :: [[String]] -> [(String, Integer, String)]
convert lists = map (\[a, b, c] -> (a, read b, c)) lists

【讨论】:

  • 这是一个非常好的解决方案,但我需要保持相同的结构,你说没有办法?
  • 对,没办法。除非您将其转换为另一种类型的列表,例如data D = S String | I Integer,然后map ((x:y:xs) -> S x : I (read y) : map S xs) list 会为您提供[[D]],然后您可以根据需要对其进行处理。
  • 我更喜欢这种方式:convert = map ([a,b,c] -> (a, (read b), c))
  • Daniel 我已经按照你所说的尝试过转换列表的类型,但是当我运行此代码时:map ((x:y:xs) -> S x : I (read y) : map S xs) [["sd","45","b"],["j","54","g"],["a","33","d"]] 我收到此错误Pattern syntax in expression context: (x : y : xs) -> S x : I (read y) : map S xs 但如果这有效,那就完美了,完全我需要什么
  • 应该是map (\(x:y:xs) -> S x : I (read y) : map S xs) listconvert = map (\[a,b,c] -> (a, (read b), c))
猜你喜欢
  • 2012-09-29
  • 2017-02-13
  • 1970-01-01
  • 1970-01-01
  • 2010-12-27
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-06-11
相关资源
最近更新 更多