Чтение в CSV-файле и сортировка в Python - PullRequest
0 голосов
/ 13 апреля 2011

Я пытаюсь прочитать файл CSV, который выглядит следующим образом:

ruby,2,100
diamond,1,400
emerald,3,250
amethyst,2,50
opal,1,300
sapphire,2,500
malachite,1,60

Вот код, с которым я экспериментировал.

class jewel:
    def __init__(gem, name, carat, value):
            gem.name = name
            gem.carot = carat
            gem.value = value
    def __repr__(gem):
            return repr((gem.name, gem.carat, gem.value))

jewel_objects = [jewel('diamond', '1', 400),
                 jewel('ruby', '2', 200),
                 jewel('opal', '1', 600),
                ]

aList = [sorted(jewel_objects, key=lambda jewel: (jewel.value))]
print aList

Я хотел бы прочитать значения и назначить им имя, карат и значение, но я не уверен, как это сделать. Затем, как только я получу их прочитать, я бы хотел отсортировать их по стоимости за карат, так что стоимость / карат. Я довольно много искал и потерпел неудачу. Заранее большое спасибо за помощь.

Ответы [ 5 ]

2 голосов
/ 13 апреля 2011

Здесь нужно сделать две вещи, во-первых, это загрузка данных в объекты.Я рекомендую вам посмотреть модуль 'csv' в стандартной библиотеке python для этого.Он очень полный и прочтет каждую строку и сделает ее легко доступной

CSV docs: http://docs.python.org/library/csv.html

Я бы создал список объектов, а затем реализовал либо cmp функция в вашем объекте, или (если вы используете более старую версию python) вы можете передать функцию в sorted (), которая будет определять ее.Вы можете получить больше информации о сортировке в вики Python

Wiki docs: http://wiki.python.org/moin/HowTo/Sorting

Вы могли бы реализовать функцию cmp в своем классе (это может бытьнемного эффективнее, но здесь я описываю)

def __cmp__(gem, other):
    if (gem.value / gem.carot) < (other.value / other.carot):
        return -1
    elif (gem.value / gem.carot) > (other.value / other.carot): 
        return 1
    else:
        return 0
0 голосов
/ 13 апреля 2011
import csv
import operator

class Jewel(object):
    @classmethod
    def fromSeq(cls, seq):
        return cls(*seq)

    def __init__(self, name, carat, value):
        self.name  = str(name)
        self.carat = float(carat)
        self.value = float(value)

    def __repr__(self):
        return "{0}{1}".format(self.__class__.__name__, (self.name, self.carat, self.value))

    @property
    def valuePerCarat(self):
        return self.value / self.carat

def loadJewels(fname):
    with open(fname, 'rb') as inf:
        incsv = csv.reader(inf)
        jewels = [Jewel.fromSeq(row) for row in incsv if row]
    jewels.sort(key=operator.attrgetter('valuePerCarat'))
    return jewels

def main():
    jewels = loadJewels('jewels.csv')
    for jewel in jewels:
        print("{0:35} ({1:>7.2f})".format(jewel, jewel.valuePerCarat))

if __name__=="__main__":
    main()

производит

Jewel('amethyst', 2.0, 50.0)        (  25.00)
Jewel('ruby', 2.0, 100.0)           (  50.00)
Jewel('malachite', 1.0, 60.0)       (  60.00)
Jewel('emerald', 3.0, 250.0)        (  83.33)
Jewel('sapphire', 2.0, 500.0)       ( 250.00)
Jewel('opal', 1.0, 300.0)           ( 300.00)
Jewel('diamond', 1.0, 400.0)        ( 400.00)    
0 голосов
/ 13 апреля 2011

Для анализа реальных данных CSV (значений, разделенных запятыми) вы можете использовать модуль CSV, который включен в последние версии Python.

CSV - это набор соглашений, а не стандарт. Образцы данных, которые вы показываете, простые и регулярные, но в CSV обычно есть некоторые уродливые угловые случаи для цитирования, где содержимое любого поля может иметь встроенные запятые, например.

Вот очень грубая программа, основанная на вашем коде, которая выполняет наивный анализ данных (разделение на строки, затем разделение каждой строки запятыми). Он не будет обрабатывать любые данные, которые не разделяются на точное количество полей, а также те, где числовые поля неправильно анализируются функциями Python int() и float() (конструкторами объектов). Другими словами, это не содержит ни проверки ошибок, ни обработки исключений.

Тем не менее, я держал это намеренно простым, чтобы его можно было легко сравнить с вашими грубыми заметками. Также обратите внимание, что я использовал обычные соглашения Python, касающиеся ссылок на себя в определении класса. (Практически единственный раз, когда для них используются имена, отличные от «self», - это при программировании «мета-класса» ... написание классов, которые динамически создают другие классы. Любой другой случай почти наверняка вызовет серьезную озабоченность опытные программисты на Python, смотрящие на ваш код).

#!/usr/bin/env python
class Jewel:
    def __init__(self, name, carat, value):
        self.name = name
        self.carat = int(carat)
        self.value = float(value)
        assert self.carat != 0      # Division by zero would result from this
    def __repr__(self):
        return repr((self.name, self.carat, self.value))

if __name__ == '__main__':
    sample='''ruby,2,100
diamond,1,400
emerald,3,250
amethyst,2,50
opal,1,300
sapphire,2,500
malachite,1,60'''

    these_jewels = list()
    for each_line in sample.split('\n'):
        gem_type, carat, value = each_line.split(',')
        these_jewels.append(Jewel(gem_type, carat, value))
        # Equivalently: 
        # these_jewels.append(Jewel(*each_line.split(',')))

    decorated = [(x.value/x.carat, x) for x in these_jewels]
    results = [x[1] for x in sorted(decorated)]
    print '\n'.join([str(x) for x in results])

Синтаксический анализ здесь выполняется просто с использованием строкового метода .split(), а данные извлекаются в имена с использованием синтаксиса Python «распаковка кортежей» (это не удастся, если в какой-либо строке ввода будет указано неправильное количество полей).

Альтернативный синтаксис для этих двух строк использует синтаксис Python «применить». Префикс * для аргумента приводит к его распаковке в отдельные аргументы, которые передаются в экземпляр класса Jewel().

В этом коде также используется широко распространенный (и широко рекомендуемый) шаблон DSU (декорирование, сортировка, декорирование) для сортировки в некотором поле ваших данных. Я «декорирую» данные, создавая серию кортежей: (вычисленное значение, ссылка на объект), а затем «декорирую» отсортированные данные таким образом, который, я надеюсь, вам понятен. (Это было бы сразу понятно любому опытному программисту на Python).

Да, весь блок DSU может быть сведен к одной строке; Я выделил это здесь для разборчивости и педагогических целей.

Опять же, этот пример кода предназначен исключительно для вашего назидания. Вы должны использовать модуль CSV для любых реальных данных; и вы должны ввести обработку исключений либо в разборе, либо в обработке Jewel.__init__ (для преобразования числовых данных в правильные типы Python. (Также обратите внимание, что вам следует рассмотреть возможность использования модуля Python Decimal вместо float() s для представления денежных значений ... или, по крайней мере, хранения значений в центах или миллах и использования собственных функций для представления их в долларах и центах).

0 голосов
/ 13 апреля 2011

Вы можете использовать numpy структурированные массивы вместе с модулем csv и использовать numpy.sort () для сортировки данных.Следующий код должен работать.Предположим, что ваш CSV-файл называется geminfo.csv

import numpy as np
import csv

fileobj = open('geminfo.csv','rb')
csvreader = csv.reader(fileobj)

# Convert data to a list of lists
importeddata = list(csvreader)

# Calculate Value/Carat and add it to the imported data
# and convert each entry to a tuple
importeddata = [tuple(entry + [float(entry[2])/entry[1]]) for entry in importeddata]

Один из способов сортировки этих данных - использовать numpy, как показано ниже.

# create an empty array
data = np.zeros(len(importeddata), dtype = [('Stone Name','a20'),
                            ('Carats', 'f4'),
                            ('Value', 'f4'), 
                            ('valuepercarat', 'f4')]
                        )
data[:] = importeddata[:]
datasortedbyvaluepercarat = np.sort(data, order='valuepercarat')
0 голосов
/ 13 апреля 2011

Python имеет модуль CSV, который должен быть действительно полезным для вас.

http://docs.python.org/library/csv.html

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...