Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Haskell reorder list by matching value

Tags:

list

haskell

I was wondering if there's an efficient/easy way to reorder a list of a list in by matching values of another list that sets the order. More specificly, if I'd have the following list:

[["a", "1", "2"], ["b", "2", "3"]]

I'd like to order it with the following list:

["b", "a"]

resulting in the newly ordered list:

[["b", "2", "3"], ["a", "1", "2"]]

Does anyone know how this can be done?

Thanks in advance!

Best Regards, Skyfe.

like image 978
Skyfe Avatar asked Sep 30 '13 01:09

Skyfe


1 Answers

Basically this works by providing a special ordering function,

import Data.List
import Data.Ord
byLoc :: Eq a => [a] -> -- The list that we're sorting by
                 [a] -> -- First list
                 [a] -> -- Second list
                 Ordering
byLoc ords = comparing (elemIndex . head)

comparing takes a function that takes in the two lists, and looks up the first element of each in our ordering list, comparing the location.

Then we just have

sortLoc ords = sortBy (byLoc ords)

and we're done. Unfortunately, this is really slow.

A faster solution is

import Data.Maybe
import Data.List
sortLoc ords xs = mapMaybe lookup ords
  where lookup e = find ((==e) . head) xs

Here we're just looking up the appropriate element in our list in the mapMaybe. If no element is found, then we just skip it.

Or if you want to support multiple elements with the same key

sortLoc ords xs = mapConcat lookup ords
  where lookup e = filter ((==e) . head) xs
like image 143
Daniel Gratzer Avatar answered Sep 23 '22 04:09

Daniel Gratzer