What is the best way to preserve the order of a list

Hi, I have a list of entities. Each entity has a priority field and an order field. The priority field contain the input values to my algorithm, the order fields contain the output value of my algorithm. My algorithm needs to assign 1 to the order field of the entity with the lowest priority value, 2 to the order field of the entity with the next lowest priority value, .... and so on. I've written a function orderByPriority that does that. However, it also does something else that is undesireable. It reorders the list. My question is, how do I preserve the ordering of entities in my list and still be able to assign the proper order values to each entity? Is there an efficient way to do this? How else might I improve my orderByPriority algorithm. Thanks -John
import Data.List
data Entity = Entity { entityId :: Int, priority :: Float, order :: Int }
initEntity = Entity { entityId = 0, priority = 0.0, order = 0 }
myList = [ initEntity { entityId = 1, priority = 8.7 }, initEntity { entityId = 2, priority = 5.4 }, initEntity { entityId = 3, priority = 2.9 }, initEntity { entityId = 4, priority = 5.4 }, initEntity { entityId = 5, priority = 1.3 }, initEntity { entityId = 6, priority = 3.5 }, initEntity { entityId = 7, priority = 9.5 } ]
comparePriority entity1 entity2 = compare (priority entity1) (priority entity2)
orderByPriority :: [Entity] -> [Entity] orderByPriority entities = assignOrder orderList 1 where orderList = sortBy comparePriority entities assignOrder [] _ = [] assignOrder (entity:entities) count = (entity { order = count }):(assignOrder entities (count + 1))
instance Show Entity where show entity = "{" ++ "entityId:" ++ (show $ entityId entity) ++ "," ++ "priority:" ++ (show $ priority entity) ++ "," ++ "order: " ++ (show $ order entity) ++ "}"

John,
My question is, how do I preserve the ordering of entities in my list and still be able to assign the proper order values to each entity? Is there an efficient way to do this? How else might I improve my orderByPriority algorithm.
Straightforwardly, you could do it like this: import List (sortBy) type Priority = Int type Order = Int order :: [Priority] -> [(Priority, Order)] order = unlabel . sortOnLab . assignOrder . sortOnPrio . label where label = zip [0 ..] unlabel = map snd sortOnLab = sortBy (\(l, _) (m, _) -> compare l m) sortOnPrio = sortBy (\(_, p) (_, q) -> compare p q) assignOrder = \xs -> zipWith (\(l, p) o -> (l, (p, o))) xs [0 ..] For instance:
order [5, 2, 3, 7] [(5,2),(2,0),(3,1),(7,3)]
HTH, Stefan

On Wed, 01 Nov 2006 10:29:18 +0100, Stefan Holdermans
sortOnLab = sortBy (\(l, _) (m, _) -> compare l m)
The following does the same: sortOnLab = sort -- Met vriendelijke groet, Henk-Jan van Tuyl -- http://Van.Tuyl.eu/ -- Using Opera's revolutionary e-mail client: https://secure.bmtmicro.com/opera/buy-opera.html?AID=789433

Henk-Jan,
sortOnLab = sortBy (\(l, _) (m, _) -> compare l m)
The following does the same: sortOnLab = sort
It does, but I kind of liked the analogy with sortOnPrio, which could have been defined in some other ways as well, of course. Cheers, Stefan

Henk-Jan van Tuyl wrote:
On Wed, 01 Nov 2006 10:29:18 +0100, Stefan Holdermans
wrote: sortOnLab = sortBy (\(l, _) (m, _) -> compare l m)
The following does the same: sortOnLab = sort Not quite, sortOnLab preserves the order of tuples with the same first element while plain sort orders them by the second. Also, only sort requires that the second element of the tuple have an Ord instance (Haskell 98 requires that sort is stable).
Test.QuickCheck.test (\xs -> sort xs == sortOnLab xs) Falsifiable, after 1 tests: [(-3,3),(-3,1)]
sortOnLab [(-3,3),(-3,1)] ==> [(-3,3),(-3,1)]
but sort [(-3,3),(-3,1)] ==> [(-3,1),(-3,3)] Also,
map fst $ sortOnLab [(2,asTypeOf),(1,const)] [1,2]
map fst $ sort [(2,asTypeOf),(1,const)]
<interactive>:1:10: No instance for (Ord (a -> a -> a)) arising from use of `sort' at <interactive>:1:10-38 Possible fix: add an instance declaration for (Ord (a -> a -> a)) In the second argument of `($)', namely `sort [(1, asTypeOf), (1, const)]' In the expression: (map fst) $ (sort [(1, asTypeOf), (1, const)]) In the definition of `it': it = (map fst) $ (sort [(1, asTypeOf), (1, const)]) Brandon
participants (4)
-
Brandon Moore
-
Henk-Jan van Tuyl
-
John Ky
-
Stefan Holdermans