13

次のように、異なるプロパティを持つオブジェクトが 1 ダースまたは 2 ダースしかないとします。

UID、名前、値、色、タイプ、場所

Location = "Boston" または Type = "Primary" のすべてのオブジェクトを呼び出せるようにしたいと考えています。古典的なデータベース クエリ タイプのもの。

ほとんどのテーブル ソリューション (pytables、*sql) は、このような小さなデータ セットに対しては実際にはやり過ぎです。すべてのオブジェクトを繰り返し処理し、データ列ごとに個別のディクショナリを作成するだけでよいでしょうか (新しいオブジェクトを追加するときにディクショナリに値を追加します)。

これにより、次のような辞書が作成されます。

{'Boston' : [234, 654, 234], 'Chicago' : [324, 765, 342] } - これらの 3 桁のエントリは、UID などを表します。

ご覧のとおり、これをクエリするのは少し面倒です。

代替案はありますか?

4

3 に答える 3

14

小さなリレーショナルの問題については、Python の組み込みのsetsを使用するのが大好きです。

location = 'Boston' OR type = 'Primary' の例で、このデータがある場合:

users = {
   1: dict(Name="Mr. Foo", Location="Boston", Type="Secondary"),
   2: dict(Name="Mr. Bar", Location="New York", Type="Primary"),
   3: dict(Name="Mr. Quux", Location="Chicago", Type="Secondary"),
   #...
}

WHERE ... OR ...次のようにクエリを実行できます。

set1 = set(u for u in users if users[u]['Location'] == 'Boston')
set2 = set(u for u in users if users[u]['Type'] == 'Primary')
result = set1.union(set2)

または、式を 1 つだけ使用します。

result = set(u for u in users if users[u]['Location'] == 'Boston'
                              or users[u]['Type'] == 'Primary')

itertoolsの関数を使用して、かなり効率的なデータのクエリを作成することもできます。たとえば、次のようなことをしたい場合GROUP BY city

cities = ('Boston', 'New York', 'Chicago')
cities_users = dict(map(lambda city: (city, ifilter(lambda u: users[u]['Location'] == city, users)), cities))

手動でインデックスを作成して (dictユーザー ID へのマッピングの場所を作成して)、作業を高速化することもできます。これが遅すぎたり扱いにくくなったりした場合は、現在 Python (2.5) 標準ライブラリに含まれているsqliteに切り替えることになるでしょう。

于 2009-09-24T14:21:30.040 に答える
6

sqliteが「やり過ぎ」になるとは思いません。2.5以降の標準のPythonが付属しているため、インストールする必要はなく、メモリまたはローカルディスクファイルのいずれかでデータベースを作成および処理できます。本当に、どうしてもっと簡単にできるのでしょうか...?初期値を含むすべてをメモリ内に置き、dictを使用してそれらの初期値を表現したい場合、たとえば...:

import sqlite3

db = sqlite3.connect(':memory:')
db.execute('Create table Users (Name, Location, Type)')
db.executemany('Insert into Users values(:Name, :Location, :Type)', [
   dict(Name="Mr. Foo", Location="Boston", Type="Secondary"),
   dict(Name="Mr. Bar", Location="New York", Type="Primary"),
   dict(Name="Mr. Quux", Location="Chicago", Type="Secondary"),
   ])
db.commit()
db.row_factory = sqlite3.Row

これで、メモリ内の小さな「db」を使用する準備が整いました。もちろん、ディスクファイルにDBを作成したり、テキストファイルやCSVなどから初期値を読み取ったりすることは難しくありません。

クエリは特に柔軟で、簡単で、簡単です。たとえば、文字列の挿入とパラメータの置換を自由に組み合わせることができます...:

def where(w, *a):
  c = db.cursor()
  c.execute('Select * From Users where %s' % w, *a)
  return c.fetchall()

print [r["Name"] for r in where('Type="Secondary"')]

[u'Mr. Foo', u'Mr. Quux']よりエレガントだが同等のように、を放出します

print [r["Name"] for r in where('Type=?', ["Secondary"])]

そしてあなたの望むクエリはただ:

print [r["Name"] for r in where('Location="Boston" or Type="Primary"')]

など。真剣に-嫌いなものは何ですか?

于 2009-09-24T15:11:08.403 に答える
2

If it's really a small amount of data, I'd not bother with an index and probably just write a helper function:

users = [
   dict(Name="Mr. Foo", Location="Boston", Type="Secondary"),
   dict(Name="Mr. Bar", Location="New York", Type="Primary"),
   dict(Name="Mr. Quux", Location="Chicago", Type="Secondary"),
   ]

def search(dictlist, **kwargs):
   def match(d):
      for k,v in kwargs.iteritems():
         try: 
            if d[k] != v: 
               return False
         except KeyError:
            return False
      return True

   return [d for d in dictlist if match(d)] 

Which will allow nice looking queries like this:

result = search(users, Type="Secondary")
于 2009-09-24T14:31:39.960 に答える