2

I have this list:

['Ben\n', '5 0 0 5 -5 \n', 'Moose\n', '5 5 0 3 0 0 \n', ...]

that carries on like that for a long time. I need to make this list into a list of tuples like this:

[('Ben', '5 0 0 5 -5'), ('Moose', '5 5 0 3 0 0'), ...] and so on.

I feel like this should be easy.
I've already opened the text file and split it into a list by line this way:

e = open("bookratings.txt", "r")
elines = e.readlines()

But I don't know where to go from here?

dawg
  • 98,345
  • 23
  • 131
  • 206
user2180683
  • 209
  • 3
  • 6

3 Answers3

5

looks like each person has associated data at its very next line, so that makes two lines of data per person. you can zip it.

lst = list(zip(*[iter(lst)]*2))
thkang
  • 11,215
  • 14
  • 67
  • 83
  • Wouldn't that return an error? The "'lst' referenced before assignment." – user2180683 Apr 15 '13 at 18:05
  • @user2180683 `lst` would be both the original and the resulting list. – poke Apr 15 '13 at 18:06
  • For the uninformed there is a lot of magic here. Care to add an explanation? – Steven Rumbalski Apr 15 '13 at 18:07
  • Also, OP was looking for a solution that strips newlines. – Steven Rumbalski Apr 15 '13 at 18:09
  • 2
    @StevenRumbalski `[iter(lst)]*2` creates a two-element-list with a single iterator as both the elements. As it’s the exact same, identical iterator, consuming items on the first list item will also consume those on the second. So when running `zip` which pairs elements from two (or more) iterators, it will keep consuming two items from the iterator (once for each list item) and group them like that. The `*list` inside will turn the list into separate arguments of the `zip` function; so everything works out. – poke Apr 15 '13 at 18:12
  • @poke: I was suggesting you edit your answer. I understand it just fine, although there was a time when it would have confused me. – Steven Rumbalski Apr 15 '13 at 18:15
  • @StevenRumbalski If it was my answer, I’d edit it, but I rather want to leave thkang the chance to do it :) – poke Apr 15 '13 at 18:18
  • @poke: Whoops. Sorry. – Steven Rumbalski Apr 15 '13 at 18:19
  • 1
    @StevenRumbalski: Although somewhat magical to those not familiar with iterators, `zip(*[iter(inputlist)*n])` is a fairly standard trick to create a 2-wise grouper. :-) – Martijn Pieters Apr 15 '13 at 18:34
  • 2
    @MartijnPieters: Right. But we're talking about an OP who opens files without using `with` and who reflexively uses `readlines` on a file. So I thought a little explanation was needed. – Steven Rumbalski Apr 15 '13 at 19:29
3

Here you go:

>>> li=['Ben\n', '5 0 0 5 -5 \n', 'Moose\n', '5 5 0 3 0 0 \n']
>>> zip(*[(e.strip() for e in li)]*2)
[('Ben', '5 0 0 5 -5'), ('Moose', '5 5 0 3 0 0')]

The zip(*[iter(s)]*n) part is based on from the Python documents on zip for idiom for clustering a data series into n-length groups.

I added the generator inside to strip the carriage returns. Once the generator expression is there, the iter is no longer needed. (Thanks @StevenRumbalski)

Of course, you mentioned that you have a file like object like so:

Ben
5 0 0 0 -5
Moose
5 5 0 3 0 0
...

If so, here is an alternative where you do not have to read the entire file in:

>>> with open('/tmp/lines.txt','r') as f:
...    it=iter(f)
...    li=[(i.strip(),it.next().strip()) for i in it]
... 
>>> li
[('Ben', '5 0 0 0 -5'), ('Moose', '5 5 0 3 0 0')]
dawg
  • 98,345
  • 23
  • 131
  • 206
0

Try like

>>a = ['Ben\n', '5 0 0 5 -5 \n', 'Moose\n', '5 5 0 3 0 0 \n']

>>b = ''.join(a).split('\n')

Now

>> c = [(b[i],b[i+1]) for i in range(0,len(b)-1,2)]

should give you the result

[('Ben', '5 0 0 5 -5 '), ('Moose', '5 5 0 3 0 0 ')]
dawg
  • 98,345
  • 23
  • 131
  • 206
aar cee
  • 239
  • 3
  • 10