1

I have a text file which stores data like name : score e.g.:

bob : 10
fred : 3
george : 5

However, I want to make it so it says

10 : bob
3 : fred
5 : george

What would the code be to flip it like that? Would I need to separate them first by removing the colon as I have managed this through this code?

file = open("Class 3.txt", "r")
t4 = (file.read())
test =''.join(t4.split(':')[0:10])
print (test)

How would I finish it and make it say the reverse?

Ryan Haining
  • 35,360
  • 15
  • 114
  • 174

3 Answers3

1

This code handles fractional scores (e.g. 9.5), and doesn't care whether there are extra spaces around the : delimiter. It should be much easier to maintain than your current code.

Class 3.txt:

bob : 10
fred : 3
george : 5

Code:

class_num = input('Which class (1, 2, or 3)? ')
score_sort = input('Sort by name or score? ').lower().startswith('s')

with open("Class " + class_num + ".txt", "r") as f:
    scores = {name.strip():float(score) for
              name,score in (line.strip().split(':') for line in f)}
    if score_sort:
        for name in sorted(scores, key=scores.get, reverse=True):
            print(scores.get(name), ':', name)
    else:
        for name in sorted(scores):
            print(name, ':', scores.get(name))

Input:

3
scores

Output:

10.0 : bob
5.0 : george
3.0 : fred

Input:

3
name

Output:

bob : 10.0
fred : 3.0
george : 5.0
TigerhawkT3
  • 48,464
  • 6
  • 60
  • 97
0

First, this is going to be a lot harder to do whole-file-at-once than line-at-a-time.

But, either way, you obviously can't just split(':') and then ''.join(…). All that's going to do is replace colons with nothing. You obviously need ':'.join(…) to put the colons back in.

And meanwhile, you have to swap the values around on each side of each colon.

So, here's a function that takes just one line, and swaps the sides:

def swap_sides(line):
    left, right = line.split(':')
    return ':'.join((right, left))

But you'll notice there's a few problems here. The left has a space before the colon; the right has a space after the colon, and a newline at the end. How are you going to deal with that?

The simplest way is to just strip out all the whitespace on both sides, then add back in the whitespace you want:

def swap_sides(line):
    left, right = line.split(':')
    return ':'.join((right.strip() + ' ', ' ' + left.strip())) + '\n'

But a smarter idea is to treat the space around the colon as part of the delimiter. (The newline, you'll still need to handle manually.)

def swap_sides(line):
    left, right = line.strip().split(' : ')
    return ' : '.join((right.strip(), left.strip())) + '\n'

But if you think about it, do you really need to add the newline back on? If you're just going to pass it to print, the answer is obviously no. So:

def swap_sides(line):
    left, right = line.strip().split(' : ')
    return ' : '.join((right.strip(), left.strip()))

Anyway, once you're happy with this function, you just write a loop that calls it once for each line. For example:

with open("Class 3.txt", "r") as file:
    for line in file:
        swapped_line = swap_sides(line)
        print(swapped_line)
abarnert
  • 354,177
  • 51
  • 601
  • 671
  • 1
    You need to wrap the arguments to join in `()` or `[]` because it takes a single iterable. – TigerhawkT3 May 08 '15 at 23:46
  • @TigerhawkT3: Guh… thanks. :) I originally had them in a list `t4s` and then passed `t4s[::-1]`, but then decided that wasn't worth explaining here, and broke it when I tuple-unpacked the list… – abarnert May 08 '15 at 23:47
  • [It gets me too.](http://codereview.stackexchange.com/questions/87139/basic-functions-sum-len-etc-with-recursively-flattened-arguments#comment157640_87139) – TigerhawkT3 May 08 '15 at 23:51
  • @TigerhawkT3: I think whether or not it gets me each time depends on whether I've more recently used `max` or `sum`. :) – abarnert May 08 '15 at 23:54
  • see i was trying to sort my actual code out if you look at my other thread i have it will explain better what i was trying to do i tried breaking it down and do it but it didnt seem to work could you please check out my other thread see if you have any ideas – Danny Bradshaw May 08 '15 at 23:57
  • Why supply your own newline and suppress print's? – Stefan Pochmann May 09 '15 at 00:19
  • @StefanPochmann: Yeah, that is kind of silly; let me re-edit. – abarnert May 09 '15 at 00:19
  • Alternatively: `''.join(s.partition(' : ')[::-1])` (or similar - you know what I mean :p) – Jon Clements May 09 '15 at 01:24
0

Let's learn how to reverse a single line:

line = `bob : 10`
line.partition(' : ')  # ('10', ' : ', 'bob')
''.join(reversed(line.partition(' : '))  # 'bob : 10'

Now, combine with reading lines from a file:

for line in open('Class 3.txt').read().splitlines():
    print ''.join(reversed(line.partition(' : '))

Update

I am re-writing the code to read the file, line by line:

with open('Class 3.txt') as input_file:
    for line in input_file:
        line = line.strip()
        print ''.join(reversed(line.partition(' : ')))
Hai Vu
  • 37,849
  • 11
  • 66
  • 93
  • Note that `file` is no longer a builtin in 3.x, and `open` was already recommended when both existed for this purpose anyway.... – Jon Clements May 09 '15 at 01:48
  • @JonClements -- Changed from `file` to `open`. Thank you for your comment. – Hai Vu May 09 '15 at 01:56
  • You're welcome - also - since files are iterable over (line by line)... you can just do `for line in open('Class 3.txt')` then `print ''.join(reversed(line.partition(' : ')))` that doesn't require reading the whole file into memory, then breaking it into a list and then iterating over that list... It certainly won't matter in this case - but it's always good to promote good practice to the people attempting to learn on the site :) (could even throw in a use of the `with` statement here!) – Jon Clements May 09 '15 at 01:59