2

I need to check if a Python list consists of two equal halves. For example, this list does:

[6, 2, 0, 2, 3, 2, 6, 2, 0, 2, 3, 2]

and this doesn't

[6, 2, 0, 2, 4, 6]

I've tried this check: len(lst) % 2 == 0 and lst[:len(lst)//2] == lst[len(lst)//2:] but it seems to be too slow for bigger lists. Any other solutions?

planetp
  • 14,248
  • 20
  • 86
  • 160
  • The solution is about slicing without copying, but python doesn't seem a builtin or standard way of doing that: https://stackoverflow.com/questions/3485475/can-i-create-a-view-on-a-python-list – Leon Jun 02 '17 at 08:07
  • Can you guarantee that the input list will always have an even length? – PM 2Ring Jun 02 '17 at 08:13
  • @PM 2Ring: I use an extra check that `len(lst) % 2 == 0` – planetp Jun 02 '17 at 08:21

1 Answers1

9

It's possible to do the check without creating the two sublists. It might be faster for really big lists.

n = len(lst)//2
all(lst[i]==lst[i+n] for i in range(n))

If you want to also check that your list is of even length, you could also add

len(lst)%2==0

as a condition.

khelwood
  • 55,782
  • 14
  • 81
  • 108
  • 1
    Gah, indices. Much better. – Martijn Pieters Jun 02 '17 at 08:10
  • Bug detected - doesn't work for a list of odd length – Leon Jun 02 '17 at 08:11
  • @MartijnPieters I'm surprised that indices are better than islice. And (I think) you don't need 2 islices: you just need the islice for the back half and use the whole list for the front half, since `zip` will stop when the shortest sequence terminates. – PM 2Ring Jun 02 '17 at 08:12
  • 1
    @Leon: how so? `//` **floors** so I don't see how `n + n` would ever be greater than `n`. And the OP never defined what is the right res – Martijn Pieters Jun 02 '17 at 08:14
  • 2
    @MartijnPieters A list of odd length **never** consists of two equal halves. – Leon Jun 02 '17 at 08:14
  • So to handle odd length `lst`: immediately return False. :) – PM 2Ring Jun 02 '17 at 08:15
  • @MartijnPieters What will this code tell for the following list: `[1, 1, 0]`? In case of an odd length, the last element is ignored. – Leon Jun 02 '17 at 08:16
  • @PM2Ring islice iterates over half the list *first*; it doesn't use indexing to skip over the first half. – Martijn Pieters Jun 02 '17 at 08:16
  • 1
    @Leon: sure, different result, but there's no constraint in the question about handling odd lengths. Just add a `len(lst) % 2` test first to return `False` or raise an exception. – Martijn Pieters Jun 02 '17 at 08:18
  • @MartijnPieters I didn't mean that the solution is wrong to the extent of being unfixable. Just wanted to bring the author's attention to the overlooked case – Leon Jun 02 '17 at 08:19
  • @MartijnPieters Ah, of course. In general, it's impossible for `islice` to skip to an arbitrary point in an iterable, so it _has_ to iterate. D'oh! :) – PM 2Ring Jun 02 '17 at 08:24
  • This is slightly better, but not much.. I think I'll need to use a different data structure. – planetp Jun 02 '17 at 11:11