How to convert records into Haskell structure in Haskell way?

Hi, Say I have something like this: [ Record { item = "A1", value = "0" } , Record { item = "B1", value = "13" } , Record { item = "A2", value = "2" } , Record { item = "B2", value = "10" } ] How to convert it into: [ XXInfo { name = "A", value1 = "0", value2 = "2" } , XXInfo { name = "B", value1 = "13", value2 = "10" } ] If XXInfo has a lot of members. And sometimes the original data might be not integrity. -- 竹密岂妨流水过 山高哪阻野云飞

Am Dienstag 03 November 2009 02:29:56 schrieb Magicloud Magiclouds:
Hi, Say I have something like this: [ Record { item = "A1", value = "0" } , Record { item = "B1", value = "13" } , Record { item = "A2", value = "2" } , Record { item = "B2", value = "10" } ] How to convert it into: [ XXInfo { name = "A", value1 = "0", value2 = "2" } , XXInfo { name = "B", value1 = "13", value2 = "10" } ] If XXInfo has a lot of members. And sometimes the original data might be not integrity.
Could you be a little more specific about what you want to achieve? As a first guess, you might use something like import Data.List import Data.Ord (comparing) import Data.Function (on) sortedRecords = sortBy (comparing item) records recordGroups = groupBy ((==) `on` (head . item)) sortedRecords -- now comes the tricky part, converting the groups to XXinfo -- if all groups are guaranteed to have the appropriate number of -- elements, you can use xxInfo [Record (c:_) v1, Record _ v2] = XXinfo [c] v1 v2 -- and then xxInfos = map xxInfo recordGroups -- if the groups may have different numbers of elements, it's going to be uglier

This is pretty much it, with one thing left.
I got the original data from outside. Out of no reason, the data could
be incomplete.
For example, XXInfo has two members, this is the correct case. But the
data I got may only contain only one member's information, with the
other one totally lost. Kind like:
[ Record { item = "A1", value = "0" } ]
This is not a legal XXInfo, I have to deal with it.
Plus, there are 28 members of XXInfo, so xxInfo of yours would be very ugly.
On Tue, Nov 3, 2009 at 9:55 AM, Daniel Fischer
Am Dienstag 03 November 2009 02:29:56 schrieb Magicloud Magiclouds:
Hi, Say I have something like this: [ Record { item = "A1", value = "0" } , Record { item = "B1", value = "13" } , Record { item = "A2", value = "2" } , Record { item = "B2", value = "10" } ] How to convert it into: [ XXInfo { name = "A", value1 = "0", value2 = "2" } , XXInfo { name = "B", value1 = "13", value2 = "10" } ] If XXInfo has a lot of members. And sometimes the original data might be not integrity.
Could you be a little more specific about what you want to achieve?
As a first guess, you might use something like
import Data.List import Data.Ord (comparing) import Data.Function (on)
sortedRecords = sortBy (comparing item) records
recordGroups = groupBy ((==) `on` (head . item)) sortedRecords
-- now comes the tricky part, converting the groups to XXinfo -- if all groups are guaranteed to have the appropriate number of -- elements, you can use xxInfo [Record (c:_) v1, Record _ v2] = XXinfo [c] v1 v2
-- and then
xxInfos = map xxInfo recordGroups
-- if the groups may have different numbers of elements, it's going to be uglier _______________________________________________ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
-- 竹密岂妨流水过 山高哪阻野云飞

On Mon, Nov 2, 2009 at 5:29 PM, Magicloud Magiclouds
Hi, Say I have something like this: [ Record { item = "A1", value = "0" } , Record { item = "B1", value = "13" } , Record { item = "A2", value = "2" } , Record { item = "B2", value = "10" } ] How to convert it into: [ XXInfo { name = "A", value1 = "0", value2 = "2" } , XXInfo { name = "B", value1 = "13", value2 = "10" } ] If XXInfo has a lot of members. And sometimes the original data might be not integrity.
This is a function from my library that I use a lot: -- | Group the unsorted list into @(key x, xs)@ where all @xs@ compare equal -- after @key@ is applied to them. List is returned in sorted order. keyed_group_with :: (Ord b) => (a -> b) -> [a] -> [(b, [a])] keyed_group_with key = map (\gs -> (key (head gs), gs)) . groupBy ((==) `on` key) . sortBy (compare `on` key) -- You can use it thus, Left for errors of course: to_xx records = map convert (keyed_group_with item records) where convert (name, [Record _ v1, Record _ v2]]) = Right (XXInfo name v1 v2) convert (name, records) = Left (name, records)

You might want to look at the code out there that processes command line
options by creating record setting functions, which then are foldl'-ed to
create an updated structure. See
http://leiffrenzel.de/papers/commandline-options-in-haskell.html at the
bottom of the page. I suspect you can easily create a conversion function
(of functions) that does what you want.
On Mon, Nov 2, 2009 at 6:38 PM, Evan Laforge
On Mon, Nov 2, 2009 at 5:29 PM, Magicloud Magiclouds
wrote: Hi, Say I have something like this: [ Record { item = "A1", value = "0" } , Record { item = "B1", value = "13" } , Record { item = "A2", value = "2" } , Record { item = "B2", value = "10" } ] How to convert it into: [ XXInfo { name = "A", value1 = "0", value2 = "2" } , XXInfo { name = "B", value1 = "13", value2 = "10" } ] If XXInfo has a lot of members. And sometimes the original data might be not integrity.
This is a function from my library that I use a lot:
-- | Group the unsorted list into @(key x, xs)@ where all @xs@ compare equal -- after @key@ is applied to them. List is returned in sorted order. keyed_group_with :: (Ord b) => (a -> b) -> [a] -> [(b, [a])] keyed_group_with key = map (\gs -> (key (head gs), gs)) . groupBy ((==) `on` key) . sortBy (compare `on` key)
-- You can use it thus, Left for errors of course:
to_xx records = map convert (keyed_group_with item records) where convert (name, [Record _ v1, Record _ v2]]) = Right (XXInfo name v1 v2) convert (name, records) = Left (name, records) _______________________________________________ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
participants (4)
-
Daniel Fischer
-
Evan Laforge
-
Magicloud Magiclouds
-
Scott Michel