Isen
Isen

Reputation: 79

Sorting an imported list not working

I am trying to sort an imported list then display it but I have tried all sorts of things and it didnt work.

Here is an exemple of the list:

pommes : 54
bananes : 18
oranges : 30


ananas :12
clémentines    :77
cerises de terre:    43

The output should be ordered alphabeticaly

This is what I am getting

['\n', '\n', '\n', '\n', '\n', '\n', '\n', '\n', '\n', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', '0', '1', '1', '2',
 '3', '3', '4', '4', '5', '7', '7', '8', ':', ':', ':', ':', ':', ':', 'a', 'a', 'a', 'a', 'a', 'a', 'b', 'c', 'c', 'd', 'e', 'e', 'e', 'e', 'e', 'e', 'e', 'e'
, 'e', 'e', 'g', 'i', 'i', 'l', 'm', 'm', 'm', 'n', 'n', 'n', 'n', 'n', 'n', 'n', 'o', 'o', 'p', 'r', 'r', 'r', 'r', 's', 's', 's', 's', 's', 's', 's', 't', 't
', 'é']

Here's is my code

import sys

def liste(entree):
    try:
        ouvrir = open("data2.txt")
    except IOError:
        message1 = "Le fichier data2 n'existe pas."
        return message1
    lecture = ouvrir.read()
    if len(entree) < 1:
        message2 = "Il faut préciser le nom du fichier à traiter"
        return message2
    elif len(entree) > 1:
        message3 = "Un seul argument est attendu, soit le nom du fichier à traiter."
        return message3
    else:
        return lecture

def main():
    while True:
        entree = sys.argv[1:]
        choix = str(entree)
        texte = "data2.txt"
        if texte in choix:
            message4 = liste(entree)
            message4 = sorted(message4)
            print(message4)
            break
        else:
            print("Il faut préciser le nom du fichier à traiter")
            exit()

if __name__ == "__main__":
    main()

Upvotes: 1

Views: 121

Answers (3)

gboffi
gboffi

Reputation: 25073

Your statements

ouvrir = open("data2.txt")
lecture = ouvrir.read()

works like this: open("data2.txt") returns a file object that you label with the name ouvrir, the method .read() returns a string coinciding with the contents of "data2.txt" and you label this string as lecture.

When you reference lecture you reference a string and not a list...

A clever way to solve the problem uses a string method: splitlines(); it takes a string and returns a list whose elements are strings obtained by splitting the original string across newlines.

lecture = ouvrir.read()        # lecture is a string
lecture = lecture.splitlines() # lecture is now a list of strings (lines)

and this is what you need to keep going. Please note that, as the original content is splitted on newlines, no newlines (i.e., '\n' characters) are present any more in the lines you are going to sort...

To complete my answer I have to mention that methods can be chained

lecture = ouvrir.read().splitlines()

Addendum

Another possibility leaves alone your liste() function (note that liste is a misleading name, as your function returns a string, not a list...) and post-process the string returned by liste — or I'd rather say, other possibilities even if "There should be one-- and preferably only one --obvious way to do it"...

(...)
       if texte in choix:
            message4 = liste(entree)          ## m4 is a string of characters
            message4 = message4.splitlines()  ## m4 is a list of strings,
                                              ##    one string <-> one line in file
            message4 = sorted(message4)       ## m4 contents are sorted now

            for line in message4:             ## let's do something for each line in m4
                if line:                      ## that is, if the line contains something
                    print(line)
            print('############################# alternative')
            lines = sorted(l for l in liste(entree).splitlines() if l)
            for line in lines: print(line)
            print('############################# alternative')
            for line in sorted(l for l in liste(entree).splitlines() if l): print(line)
            print('############################# alternative')
            print('\n'.join(sorted(l for l in liste(entree).splitlines() if l)))
            break
        else:
(...)

Upvotes: 1

ChuckCottrill
ChuckCottrill

Reputation: 4444

Try readlines, (see this answer: How do I read a file line-by-line into a list?, also see: Reading a text file and splitting it into single words in python).

Oh, and 'with open()' is idiomatic (moreso than try),

with open("data2.txt") as ouvrir:
    lines = ouvrir.readlines()
print sorted(lines)

Assuming each line contains a single word, you are done.

Suppose you want to treat each line as words (one or more words per line), sort the words on each line, and sort the lines,

#open file "data2.txt" and readlines into list
#split each line into words and sort that list of sorted lines
#words = list ( list ( word ) )
with open("data2.txt") as ouvrir:
    lines = ouvrir.readlines()
    line_words = [ x for x in [ line.split(":") for line in lines ] ]
    #line_names = [ x[0] for x in [ line.split(":") for line in lines ] ]
print sorted(line_words)

Suppose each line has one or more words, and you want a sorted list of words? The following flattens the nested list of words into a single list of words,

#open file "data2.txt" and readlines into list
#split each line into words, flatten into single list of words
#words = list ( word )
with open("data2.txt") as ouvrir:
    lecture = ouvrir.readlines()
    words = [ word for line in lecture for word in line.split() ]
print sorted(words)

Suppose your lines have key:value pairs, e.g. "Apple: 23"?, then you want something different

Your program combines examining entree (slice sys.argv[1:]) with opening and reading a file. You should separate those two functions. Here is one way to revise your code,

import sys

def liste(texte,entree):
    if len(entree) < 1:
        return "Il faut préciser le nom du fichier à traiter"
    elif len(entree) > 1:
        return "Un seul argument est attendu, soit le nom du fichier à traiter."
    with open(texte) as ouvrir:
        lecture = ouvrir.readlines()
        words = [ x.split(":")[0].strip() for x in [ line.strip() for line in lecture ] ]
        words = [ x for x in words if len(x) > 1 ] #filter, remove short words (blanks)
        return lecture
    return "Le fichier {} n'existe pas.".format(texte)

def main():
    while True:
        entree = sys.argv[1:]
        choix = str(entree)
        texte = "data2.txt"
        if texte in choix:
            message4 = sorted(liste(texte,entree))
            print(message4)
            for el in message4: print(el)
            break
        else:
            print("Il faut préciser le nom du fichier à traiter")
            break

if __name__ == "__main__":
    main()
    exit()

Upvotes: 1

Ananth
Ananth

Reputation: 4397

You need to use the readlines method here, which reads the lines into a list, rather than read method which returns all contents into a string.

lecture = ouvrir.readlines()

Final program:

import sys

def liste(entree):
    try:
        ouvrir = open("data2.txt")
    except IOError:
        message1 = "Le fichier data2 n'existe pas."
        return message1
    lecture = ouvrir.readlines()
    if len(entree) < 1:
        message2 = "Il faut préciser le nom du fichier à traiter"
        return message2
    elif len(entree) > 1:
        message3 = "Un seul argument est attendu, soit le nom du fichier à traiter."
        return message3
    else:
        return lecture

def main():
    while True:
        entree = sys.argv[1:]
        choix = str(entree)
        texte = "data2.txt"
        if texte in choix:
            message4 = liste(entree)
            print(message4)
            message4 = sorted(message4)
            print(message4)
            break
        else:
            print("Il faut préciser le nom du fichier à traiter")
            exit()

if __name__ == "__main__":
    main()

Run this:

$ python3 french-program.py data2.txt                                                                         
['Orange\n', 'Apple\n', 'Banada']
['Apple\n', 'Banada', 'Orange\n']

Upvotes: 2

Related Questions