Структура данных для поддержания табличных данных в памяти?

Используйте приведенный ниже код для сортировки в алфавитном порядке:

    NSArray *unsortedStrings = @[@"Verdana", @"MS San Serif", @"Times New Roman",@"Chalkduster",@"Impact"];

    NSArray *sortedStrings =
    [unsortedStrings sortedArrayUsingSelector:@selector(compare:)];

    NSLog(@"Unsorted Array : %@",unsortedStrings);        
    NSLog(@"Sorted Array : %@",sortedStrings);

Ниже приведен журнал консоли:

2015-04-02 16:17:50.614 ToDoList[2133:100512] Unsorted Array : (
    Verdana,
    "MS San Serif",
    "Times New Roman",
    Chalkduster,
    Impact
)

2015-04-02 16:17:50.615 ToDoList[2133:100512] Sorted Array : (
    Chalkduster,
    Impact,
    "MS San Serif",
    "Times New Roman",
    Verdana
)
72
задан Brian Tompsett - 汤莱恩 28 September 2016 в 22:35
поделиться

4 ответа

Наличие в памяти «таблицы», которая требует поиска, сортировки и произвольной агрегации, действительно требует SQL. Вы сказали, что пробовали SQLite, но понимаете ли вы, что SQLite может использовать базу данных только в памяти?

connection = sqlite3.connect(':memory:')

Затем вы можете создавать / удалять / запрашивать / обновлять таблицы в памяти со всеми функциями SQLite и без файлов, оставшихся, когда все готово. Что касается Python 2.5, sqlite3 находится в стандартной библиотеке, так что это не совсем уж "излишний" IMO.

Вот пример того, как можно создать и заполнить базу данных:

import csv
import sqlite3

db = sqlite3.connect(':memory:')

def init_db(cur):
    cur.execute('''CREATE TABLE foo (
        Row INTEGER,
        Name TEXT,
        Year INTEGER,
        Priority INTEGER)''')

def populate_db(cur, csv_fp):
    rdr = csv.reader(csv_fp)
    cur.executemany('''
        INSERT INTO foo (Row, Name, Year, Priority)
        VALUES (?,?,?,?)''', rdr)

cur = db.cursor()
init_db(cur)
populate_db(cur, open('my_csv_input_file.csv'))
db.commit()

Если вы Если бы вы действительно предпочли не использовать SQL, вам, вероятно, следует использовать список словарей:

lod = [ ] # "list of dicts"

def populate_lod(lod, csv_fp):
    rdr = csv.DictReader(csv_fp, ['Row', 'Name', 'Year', 'Priority'])
    lod.extend(rdr)

def query_lod(lod, filter=None, sort_keys=None):
    if filter is not None:
        lod = (r for r in lod if filter(r))
    if sort_keys is not None:
        lod = sorted(lod, key=lambda r:[r[k] for k in sort_keys])
    else:
        lod = list(lod)
    return lod

def lookup_lod(lod, **kw):
    for row in lod:
        for k,v in kw.iteritems():
            if row[k] != str(v): break
        else:
            return row
    return None

Затем тестирование дает:

>>> lod = []
>>> populate_lod(lod, csv_fp)
>>> 
>>> pprint(lookup_lod(lod, Row=1))
{'Name': 'Cat', 'Priority': '1', 'Row': '1', 'Year': '1998'}
>>> pprint(lookup_lod(lod, Name='Aardvark'))
{'Name': 'Aardvark', 'Priority': '1', 'Row': '4', 'Year': '2000'}
>>> pprint(query_lod(lod, sort_keys=('Priority', 'Year')))
[{'Name': 'Cat', 'Priority': '1', 'Row': '1', 'Year': '1998'},
 {'Name': 'Dog', 'Priority': '1', 'Row': '3', 'Year': '1999'},
 {'Name': 'Aardvark', 'Priority': '1', 'Row': '4', 'Year': '2000'},
 {'Name': 'Wallaby', 'Priority': '1', 'Row': '5', 'Year': '2000'},
 {'Name': 'Fish', 'Priority': '2', 'Row': '2', 'Year': '1998'},
 {'Name': 'Zebra', 'Priority': '3', 'Row': '6', 'Year': '2001'}]
>>> pprint(query_lod(lod, sort_keys=('Year', 'Priority')))
[{'Name': 'Cat', 'Priority': '1', 'Row': '1', 'Year': '1998'},
 {'Name': 'Fish', 'Priority': '2', 'Row': '2', 'Year': '1998'},
 {'Name': 'Dog', 'Priority': '1', 'Row': '3', 'Year': '1999'},
 {'Name': 'Aardvark', 'Priority': '1', 'Row': '4', 'Year': '2000'},
 {'Name': 'Wallaby', 'Priority': '1', 'Row': '5', 'Year': '2000'},
 {'Name': 'Zebra', 'Priority': '3', 'Row': '6', 'Year': '2001'}]
>>> print len(query_lod(lod, lambda r:1997 <= int(r['Year']) <= 2002))
6
>>> print len(query_lod(lod, lambda r:int(r['Year'])==1998 and int(r['Priority']) > 2))
0

Лично мне больше нравится версия SQLite, поскольку она лучше сохраняет ваши типы (без дополнительного кода преобразования в Python) и легко расширяется для соответствия будущим требованиям. Но опять же, мне вполне комфортно с SQL, поэтому YMMV.

76
ответ дан 24 November 2019 в 12:39
поделиться

Иметь класс таблицы, строки которого представляют собой список объектов строк dict или лучше

В таблице не добавляются строки напрямую, но есть метод, который обновляет несколько карт поиска, например, для имени если вы не добавляете строки по порядку или id не являются последовательными, вы также можете использовать idMap например

class Table(object):
    def __init__(self):
        self.rows =  []# list of row objects, we assume if order of id
        self.nameMap = {} # for faster direct lookup for row by name

    def addRow(self, row):
        self.rows.append(row)
        self.nameMap[row['name']] = row

    def getRow(self, name):
        return self.nameMap[name]


table = Table()
table.addRow({'ID':1,'name':'a'})
6
ответ дан 24 November 2019 в 12:39
поделиться

First, given that you have a complex data retrieval scenario, are you sure even SQLite is overkill?

You'll end up having an ad hoc, informally-specified, bug-ridden, slow implementation of half of SQLite, paraphrasing Greenspun's Tenth Rule.

That said, you are very right in saying that choosing a single data structure will impact one or more of searching, sorting or counting, so if performance is paramount and your data is constant, you could consider having more than one structure for different purposes.

Above all, measure what operations will be more common and decide which structure will end up costing less.

5
ответ дан 24 November 2019 в 12:39
поделиться

Лично я бы использовал список списков строк. Поскольку данные для каждой строки всегда находятся в одном и том же порядке, вы можете легко сортировать по любому из столбцов, просто обращаясь к этому элементу в каждом из списков. Вы также можете легко подсчитывать на основе определенного столбца в каждом списке, а также выполнять поиск. По сути, это максимально приближено к двумерному массиву.

На самом деле единственный недостаток здесь заключается в том, что вам нужно знать, в каком порядке находятся данные, и если вы измените этот порядок, вам придется изменить свой процедуры поиска / сортировки для соответствия.

Еще одна вещь, которую вы можете сделать, - это иметь список словарей.

rows = []
rows.append({"ID":"1", "name":"Cat", "year":"1998", "priority":"1"})

Это позволит избежать необходимости знать порядок параметров, чтобы вы могли просматривать каждое поле «год» в списке .

19
ответ дан 24 November 2019 в 12:39
поделиться
Другие вопросы по тегам:

Похожие вопросы: