2016-07-17 3 views
0

私はいくつかの対になったオブジェクトを同じレベル優先度で一緒にリンクしています。それらは固定長のタプルとしてグループ化することができ、すべてがリストになければなりません。いくつかのオブジェクトタイプは一意であり、他のタイプは共通であり得る)。 たとえば、このデータ構造では、オブジェクト、オブジェクト名(両方が一意)、オブジェクト型およびbool(どちらも共通)があります。独立したデータアクセスのようなタプルのリスト

[(Banana, myBanana, fruit, True), 
(Water, myWater, liquid, True), 
(Car, myCar, vehicle, False)] 

次に、固有のオブジェクトを知っている他のデータに簡単にアクセスする方法を見つける必要があります。私が「バナナ」を拾い上げると(myBanana、果物、真)、「myCar」を選ぶと(Car、vehicle、False)が得られます。共通の値でアクセスする必要はありませんが、データ構造に共通の値があり、変化する可能性があることを示すためだけにあります。順序は重要ではないかもしれません、私は単純化のためにリストを使用しました。

明らかに、固有のオブジェクトの1つをそれぞれキーとして使用して2つの辞書を作成できますが、実際にはよりユニークなオブジェクトタイプといくつかの関連データ(最後のブールなど)を変更する可能性があります。私に他のすべての辞書を変更させてください。 各データ型ごとに別々のリストを含むクラスを作成し、選択した「列」に対してindex()を使用し、他のリスト[インデックス]値のタプルを返すこともできます。 これを行うには、より優れた、より速い、より良い、より洗練された方法がありますか?

+0

おそらく名前付きタプルを使用しますか? https://docs.python.org/3/library/collections.html#collections.namedtuple –

+0

これは私の教科書クラスのようです。 – msvalkon

+0

@TedKleinBergman名前付きタプルを使用することはできません。なぜなら、私が書いたように、「共通」の値(最後のブールなど)を変更する必要があるからです。 – musicamante

答えて

0

私はクラスを作る際に解決策を試しました。それは動作し、私はかなりpythonicだと思う。それは2つのdictを使用します:それぞれがユニークなものがコモンズのキーであり、1つのdictがキーを含むものです。誰も答えを得ていないので、私はそれを分かち合うと思った。

class Foo(object): # Didn't know how to name it. 

    def __init__(self): 
     self.value = dict() 
     self.key = dict() 

    def add(self, keys, values): 
     for key in keys: 
      self.value[key] = values # Each key reference the values. 
      self.key[key] = keys # Each key reference to all the keys that reference the values. 

    def remove(self, key): 
     keys = self.key[key] # Get all the keys that reference the same values as key. 
     for key in keys: 
      del self.key[key] # Delete all keys associated with the key. 
      del self.value[key] # Delete all values associated with the key. 

    def __getitem__(self, key): 
     return self.value[key] 

    def __setitem__(self, key, value): 
     keys = self.key[key] # Get all the keys that reference the same values as key. 
     for key in keys: 
      self.value[key] = value # Make all the keys reference the new value. 

    def __repr__(self): 
     output = [] 
     temp = [] 
     for key in self.key: 
      if key not in temp: 
       temp.extend(self.key[key]) 
       output.append("{}: {}".format(self.key[key], self.value[key])) 
     return "{" + ", ".join(output) + "}" 

私は試してみましたが、期待通りに動作します。

a = Foo() 
a.add(["Car", "My_car"], [0, True]) 

print(a["Car"]) # OUTPUT: [0, True] 
print(a["My_car"]) # OUTPUT: [0, True] 

a["Car"][0] = -1 
print(a["Car"]) # OUTPUT: [-1, True] 
print(a["My_car"]) # OUTPUT: [-1, True] 

a["Car"][1] = False 
print(a["Car"]) # OUTPUT: [-1, False] 
print(a["My_car"]) # OUTPUT: [-1, False] 

a["Car"] = [100, None] 
print(a["Car"]) # OUTPUT: [100, None] 
print(a["My_car"]) # OUTPUT: [100, None] 

a["My_car"][0] = -1 
print(a["My_car"]) # OUTPUT: [-1, None] 
print(a["Car"]) # OUTPUT: [-1, None] 

a["My_car"][1] = False 
print(a["My_car"]) # OUTPUT: [-1, False] 
print(a["Car"]) # OUTPUT: [-1, False] 

a["My_car"] = [100, None] 
print(a["My_car"]) # OUTPUT: [100, None] 
print(a["Car"]) # OUTPUT: [100, None] 

print(a) # OUTPUT: {['Car', 'My_car']: [100, None]} 
a.remove("My_car") 
print(a) # OUTPUT: {} 
a.add(["Car", "My_car"], [0, True]) 
print(a) # OUTPUT: {['Car', 'My_car']: [0, True]} 
a.remove("Car") 
print(a) # OUTPUT: {} 

それだけでなく、複数のキーと複数の値のために動作します:

a.add(["Car", "My_car"], [0, True]) 
a.add(["Boat", "My_boat", "Sea"], [1, False, "testing"]) 
a.add(["Soap", "My_soap", "Bath", "Water"], [3]) 

print(a["Car"]) # OUTPUT: [0, True] 
print(a["My_boat"]) # OUTPUT: [1, False, 'testing'] 
print(a["Soap"]) # OUTPUT: [3] 
print(a["Water"]) # OUTPUT: [3] 

問題は、それはサイズが大きくなると、それはいくつかのメモリを使用する可能性がありますということです。

+0

編集可能な複数の値を使用するのは面白いですが、残っているキーは表示されません(これは必要なものです)。 2つの解決策が出てきましたが、その間に可能な答えとして投稿します。 – musicamante

0

私はその間に3つの異なる解決策を出しました。

1.共通辞書

最初のキーと値として辞書に形質転換された完全なグループタプルとして一意のフィールドを使用して一般的な辞書です。これはクラスを必要とせず、共通の辞書を返す関数で十分です。これは、テスト関数です:

def build_structure(data, indexes=(0,)): 
    result = {} 
    for elem in data: 
     for index in indexes: 
      result[elem[index]] = elem 
    return result 

例のリストを使用して、返される構造体は、このようなものです:データが成長したときに、すべての値が参照されるので、

{ 
Banana: {key1: Banana, key2: myBanana, value1: fruit, value2: True}, 
myBanana: {key1: Banana, key2: myBanana, value1: fruit, value2: True}, 
...: {..:..}, 
myCar: {key1: Car, key2: myCar, value1: vehicle, value2: False}, 
} 

これは、多くのメモリを食べません私はstructure['somekey']と呼ぶことができ、結果を直接得ることができるので、グループ全体の辞書は使いやすいです。値を追加するのはちょうどstructure.update(structure_func(new_data))です。実装は非常にシンプルですが、いくつかの副作用があります:検索キーを含まない(明らかに順序付けられていない)辞書を返します。検索キーなしで挿入順序を維持することを好みます。異なるキーフィールドでは、結果は上書きされます。反転軸を有するリストの

2.リスト

第二の溶液は、すべての埋め込まれたリストは、実際にグループの各々のためのフィールド値を含む元々与えられたデータから、リストのリストを使用するクラスでありますデータリスト。試験コード:

class MyStructure(object): 
    def __init__(self, data): 
     self.data = [[data[i][col] for i in range(len(data))] for col in range(len(data[0]))] 
    def get(self, col, data): 
     index = self.data[col].index(data) 
     return [self.data[c][index] for c in range(len(self.data)) if c!= col] 
    def append(self, data): 
     for i, v in enumerate(data): 
      self.data[i].append(v) 

そして、最終的な構造は次のようであろう:

[[Banana, Water, Car], 
[myBanana, myWater, myCar], 
[fruit, liquid, vehicle], 
[True, True, False]] 

(単純structure.getを(使用))第一の溶液からの唯一の欠点その検索されクエリは、最初に、指定されたフィールドのlist.index()と、他のすべての検索フィールドのデータ[field_id] [index]を含みます。また、検索クエリのフィールドIDも知っておく必要があります。リストを参照して

3.辞書

第三の溶液は、リストの元のリストとforementionedリストインデックスへの参照を持つすべてのキーフィールド、辞書を含むリストを使用するクラスです。構造は次のようになります:その辞書のために取得するには、方法がどうなるフィールドIDと検索キーを与えられた:

[{ 
    Banana: [Banana, myBanana, fruit, True], 
    Water: [Water, myWater, liquid, True], 
    [...] 
}, 
{ 
    myBanana: [Banana, myBanana, fruit, True], 
    [...] 
}] 

再度、検索クエリを呼び出すと、検索が発生する場を知ることが必要です他のフィールド値(指定されたキーを引いたもの)のリストを返します。また、すべての検索フィールドを検索し、一致する可能性のあるリストを返すメソッドを作成することもできます。

これは私が作ったテストクラスです:

class NewStructure(object): 
    def __init__(self, data): 
     self.data = data 
     self.field_dicts = [] 
     for field in range(len(data[0])): 
      self.field_dicts.append({data[index][field]:item for index, item in enumerate(data)}) 
    def get(self, column, value): 
     return [v for i, v in enumerate(self.field_dicts[column][value]) if i!=column] 
    def append(self, data): 
     self.data.append(data)  
     for index, field in enumerate(self.field_dicts):  
      field[data[index]] = self.data[-1]``` 

これは実際にははるかに複雑なソリューションですが、私はそれが他の人よりも多くの利点を持っていると思う:元のデータ構造は、これまでにも、変更されません。異なるフィールドに類似のキーがある場合主データ構造が大きくなると、主データ構造索引への参照が含まれるだけなので、辞書の実際の成長は最小限に抑えられます。与えられた例では、可能な検索フィールドとしてフィールドをすべてと使用しました。__init__に許可された検索フィールドインデックスを追加すると、最初の2つのフィールドだけが検索フィールドになることを指定するなど、参照辞書ではない4.

私は自分のシナリオに従って解決策を選択する必要があると思います。私の場合、実際には「リアルタイム」の結果は実際には必要ありません。私は最後の解決策をとって、おそらく動的メソッドの作成を追加し、クラス名にフィールド名を必要とし、structure.get_from_key1(Banana)のようなものを許可したいと思います。

しかし、私はプログラマーではない、私はただ楽しいためにこれを行う。誰かが他のアイデアを持っていれば、別の視点を知ることでも分かります。 :)

ありがとう!

PS:誰かがこの質問の方がより明確なタイトルを持っている場合は、編集していただければ幸いです。

関連する問題