0

Suppose I have a txt file, each row contains a name and age (name always unique but age can be same).

Could anyone suggest a good algorithm to print out names while their ages are in ascending/descending order? (names of people having same age don't need to keep the order in the txt)

Thanks

rhbc73
  • 739
  • 9
  • 24

3 Answers3

4

An alternative to the answer given by timegeb would be to use an itemgetter from the operator package (documentation).

from operator import itemgetter
people = [('bob', 28), ('alice', 21), ('jeff', 78)]
print(sorted(people, key=itemgetter(1), reverse=True))

Which will give you the exact same result

[('jeff', 78), ('bob', 28), ('alice', 21)]

itemgetter acts as replacement for the lambda expression.

Community
  • 1
  • 1
AlexV
  • 578
  • 8
  • 19
2

Thanks, the problem is sorting. Say we have (a, 10), (b, 5), (c, 11). Need an algorithm to sort it to (c, 11), (a, 10), (b,5)

Alright, I assume you have these tuples in a list. You can use the built-in sorted function and give it a key function which specifies the property by which the elements of your list are sorted.

>>> people = [('bob', 28), ('alice', 21), ('jeff', 78)]
>>> sorted(people, key=lambda tup: tup[1], reverse=True)
[('jeff', 78), ('bob', 28), ('alice', 21)]

Here lambda tup: tup[1] will return the second element of each tuple. This is the value by which the tuples will be sorted. reverse=True is set to sort the tuples in descending order.

timgeb
  • 76,762
  • 20
  • 123
  • 145
  • 2
    Use operator.itemgetter or operator.attrgetter instead of lambda. (attrgetter if it's a namedtuple). It's more idiomatic and also faster. – Alex Huszagh Dec 23 '15 at 00:23
  • @AlexanderHuszagh why would I need an import for such a trivial task? – timgeb Dec 23 '15 at 00:24
  • 1
    Because that's kinda the point of the builtin library. Sure, you can write a lambda, but itemgetter is specific, it's useful, and also ~50% faster. – Alex Huszagh Dec 23 '15 at 00:27
  • 1
    @AlexanderHuszagh Point taken. – timgeb Dec 23 '15 at 00:27
  • @AlexanderHuszagh If you want to put this in an answer, I will retract mine. I was busy answering, so I missed that you already adressed this issue in your comment. – AlexV Dec 23 '15 at 00:29
  • @AlexVorndran, I liked your answer. No worries. – Alex Huszagh Dec 23 '15 at 00:31
  • 2
    @timgeb: Adding to Alexander's argument, `itemgetter` does one thing, and if I see it, I know what it's doing and can't get fooled. Mistaking `lambda x: (x[1], -x[0], x[4])` for `lambda x: (x[1], x[0], x[4])` is really easy to do though, so for future maintainers, I'd use `itemgetter(1, 0, 4)` for the latter; only use `lambda` to say "I'm doing something sufficiently unique and non-obvious that the standard lib doesn't support it so pay attention". – ShadowRanger Dec 23 '15 at 00:37
1

If you put the names/ages in a dictionary with something like (will depend on your actual file format - the following assumes a name followed by age on each line, separated by whitespace):

names = {}
with open('file.txt') as f:
    for line in f:
        name, age = line.split()
    names[name] = int(age)

Then it is easy to sort - to sort by the name (not what you suggested, but just FYI), use:

sorted(names)

To sort by ages, change the key used to do the sort:

sorted(names, key=lambda i: names[i])

So, to print, you might use:

for name in sorted(names, key=lambda i: names[i]):
    print(name, names[name])
Brian
  • 2,172
  • 14
  • 24