1

How do you split a list into halves using list comprehension?

e.g. If I have [1,1,2,2,3,3,4,4,5,5] and I only want [1,1,2,2,3]

my attempts so far:

half mylist = [r | mylist!r ; r <- [0..(#mylist div 2)] ]    ||does not work

Any thoughts?

[Nb: This isn't actually Haskell but similar. ! is used for indexing list, and # gives length)

Edit::

Okay so it turns out that

half mylist = [r | r <- [mylist!0..mylist!(#mylist div 2)] ]

works, but only in list of numbers and not strings. Any clues?

tetris11
  • 817
  • 2
  • 11
  • 27

2 Answers2

8

This isn't really an appropriate thing to do with a list comprehension. List comprehensions are alternate syntax for maps and filters (and zips). Splitting a list is a fold.

As such, you should consider a different approach. E.g.

halve :: [a] -> [a]
halve [] = []
halve xs = take (n `div` 2) xs
    where n = length xs

Splitting isn't a great operation on large lists, since you take the length first (so it is always n + n/2 operations on the list. It is more appropriate for array-like types that have O(1) length and split.

Don Stewart
  • 137,316
  • 36
  • 365
  • 468
  • Appreciate the answer, but this just wont work in Miranda. There's no splitAt function... – tetris11 May 05 '12 at 18:21
  • Can I just point out that Miranda is a dead language. Nonetheless, you can still implement `splitAt` yourself, as `splitAt n xs = (take n xs, drop n xs)` -- and we should just use `take` anyway :) – Don Stewart May 05 '12 at 18:30
  • Ha trust me I'm fully aware of how dead Miranda is. Unfortunately my lecturer wrote the textbook on it, and as such we are forced to learn it. It is quite fun though. – tetris11 May 06 '12 at 10:10
  • 'take'! Wow, I completely missed that function. Yes this solves things immensely --- thanks! – tetris11 May 06 '12 at 10:10
4

Another possible solution, using a boolean guard:

half xs = [x | (x,i) <- zip xs [1..], let m = length xs `div` 2, i <= m]

But as Don Stewart says, a list comprehension is not really the right tool for this job.

Chris Rice
  • 1,390
  • 11
  • 16
  • It's at first surprising, but this is just about as efficient as dons' suggestion or the more obvious `take n mylist where n = length mylist \`div\` 2` Dunno what the Miranda implementation would do. – applicative May 05 '12 at 18:36