TableView上のFirebaseから読み取ったデータのセルをタップすると
import random import networkx as nx import matplotlib.pyplot as plt import copy import sys #要素が重複しているか def has_duplicates(seq): return len(seq) == len(set(seq)) def check(v): vmax = 0 for i in range(N-1): if v[i] + v[i+1] > vmax: vmax = v[i] + v[i+1] number = i #print("インデックス = " + str(number)) #print(v[number]) return number def create_volumes(n): #重複しないレコードの作成 V = random.sample(range(5,500), k=n) Min = min(V) ##print("最小値 = " + str(Min)) V.remove(Min) V.insert(0,Min) if check(V) < n/2: return create_volumes(n) #print("V2 = " + str(V)) #観測されるボリューム集合の生成 W = copy.copy(V) for i in range(N-1): W.append(V[i]+V[i+1]) return V, W #候補解から生成されるボリュームを観測したボリュームと比較 def compare_volumes(S, W): T = set() #観測されるボリューム集合の生成 for s in S: w = copy.copy(s) for i in range(N-1): w.append(s[i]+s[i+1]) if set(w) == set(W): #print(tuple(s)) T.add(tuple(s)) return T #1つ以上重複しているボリュームを作成(レコードは重複していない) def create_duplicates(n): data = create_volumes(n) if has_duplicates(data[1]): #重複していないならば return create_duplicates(n) else: return data def create_no_duplicates(n): data = create_volumes(n) #print(data[1]) if has_duplicates(data[1]): return data else: return create_duplicates(n) Ans = [] N = 20 #攻撃者は既知 result = create_volumes(N) V = result[0] #復元したいレコード #print("V = " + str(V)) #print("W = " + str(result[1])) W = list(set(result[1])) #攻撃者が観測するボリュームの集合 #print("生成完了") #要素を昇順に W.sort() #print("昇順W = " + str(W) + " ( |W| = " + str(len(W)) +", 重複数" + str(39-len(W)) + " )") G = nx.Graph() #step1 2頂点の和がボリュームに含まれているのならエッジを追加 #連結しているて頂点のみをエッジごと抽出 n = len(W) for i in range(n-2): for j in range(i+1,n-1): if W[i] + W[j] in W: G.add_edge(W[i], W[j]) #print("グラフ") #print("存在する枝(" + str(len(G.edges)) + ") = " + str(G.edges)) #print("抽出されたボリューム(" + str(len(G.nodes)) +"/" + str(len(W)) +") = " + str(G.nodes)) #print(list(G.neighbors(W[0]))) #step3 確定レコードである頂点を通る経路長=N-1である経路 S = [] T = [] t = [] #//集合の中にリストの集合 l = list(G.neighbors(W[0])) #最大値を生成するボリューム初期解 for w in W: if W[-1] - w in W: if w not in t: T.append([w, W[-1]-w]) t.append(W[-1]-w) #print("maxx = " + str(T)) #l2 = list(G.neighbors(W[-1])) #最小ボリュームの初期解 for i in l: #一次元配列だとループが回せないため、二次元配列にしておく S.append([W[0],i]) def right_shifts(S,G): T = [] for s in S:#各候補解ごとに right_num = len(s) - 1 l = list(G.neighbors(s[right_num]))#一番右の要素と隣合うノードを取得 for node in l: if node not in s: #同じレコードは存在しないかの判定 C = copy.copy(s) C.append(node) if C not in T: T.append(C) return T def left_shifts(S,G): T = [] for s in S:#各候補解ごとに left_num = 0 l = list(G.neighbors(s[left_num]))#一番右の要素と隣合うノードを取得 for node in l: if node not in s: #同じレコードは存在しないかの判定 C = copy.copy(s) C.insert(0,node) if C not in T: T.append(C) return T def right_shift(S,G): #print("S = " + str(S)) for i in range(N-2): #解の長さがNになるまで #print("現時点の解の長さ = " + str(i)) T = [] #j = 1 for s in S: #候補解の数 #print("候補解の " + str(j) + " 番目") #j += 1 if len(s) != N: right_num = len(s) - 1 l = list(G.neighbors(s[right_num]))#一番右の要素と隣合うノードを取得 for node in l: if node not in s: #同じレコードは存在しないかの判定 C = copy.copy(s) C.append(node) if C not in T: T.append(C) #T.append(s)#右に拡張できるがそのノードが終点である可能性があるため #print(T) S = copy.copy(T) #print("S = " + str(S)) return S #S = right_shift(S) #左に拡張 def left_shift(S,G): for i in range(N-2): T = [] for s in S: #print("s = " + str(s)) if len(s) != N: l = list(G.neighbors(s[0])) for node in l: if node not in s: #同じレコードは存在しないかの判定 C = copy.copy(s) C.insert(0,node) #先頭に要素を追加 if C not in T: T.append(C) T.append(s) S = copy.copy(T) #print("s = " + str(S)) return S #step4 確定コードが解に含まれているか 現段階では確定レコードを通る効率的なアルゴリズムが考えられていないため def confirm(S): T = [] for s in S: if len(s) == N: for i in range(len(RNodes)): if RNodes[i] not in s: break if i == len(RNodes)-1: T.append(s) return T def uni(R,L): S = R for l in L: flag = 0 for r in R: print("l = " + str(l)) print("r = " + str(r)) if l == r: flag = 1 break if flag == 0: S.append(l) return S def uni2(R,L): S = R for l in L: S.append(l) return S #これまでは、最小のボリュームが真ん中である場合を考慮して両方に拡張しないといけなかった #T = copy.copy(S) #T = right_shift(T,G) #T = left_shift(T,G) #S = left_shift(S,G) SR = [] SL = [] TR = [] TL = [] #print(N/2) for i in range(3, int(N/2) + 1): print("i = " + str(i), file=sys.stderr) SR = right_shifts(S,G) SL = left_shifts(S,G) TR = right_shifts(T,G) TL = left_shifts(T,G) S = uni2(SR,SL) T = uni2(TR,TL) print("候補解数S = " + str(len(S)), file=sys.stderr) print("候補解数T = " + str(len(T)), file=sys.stderr) #print("Smin = " + str(len(S))) #print(S) #print("Tmax = " + str(len(T))) #print(T) SS = [] for s in S: for t in T: flag = 0 for i in s: if i in t: flag = 1 break if flag == 0: if s[0] + t[0] in W: SS.append(list(reversed(s)) + t) if s[0] + t[-1] in W: SS.append(t + s) if s[-1] + t[0] in W: SS.append(s + t) if s[-1] + t[-1] in W: SS.append(t + list(reversed(s))) #print(SS) #print("解候補 = " + str(T)) #print("解の数1 = " + str(len(SS))) #T = confirm(T) #S = confirm(S) #print("解候補選別T = " + str(T)) #print("解候補選別S = " + str(S)) #print("解の数2 = " + str(len(S))) #step5 解からボリュームを計算し比較 #G1 = compare_volumes(T, W) #print("G1 = " + str(G1)) G2 = compare_volumes(SS, W) #print("G2 = " + str(G2)) #G3 = G1|G2 #print("候補解(" + str(len(G2)) + "個) = " + str(G2)) #print("真の解 = " + str(V)) if len(G2) == 1: print("unique") elif len(G2) > 1: print("Ambiguous") else: print("候補解の数がゼロ")
didSelectRowAt内に
detailVC.idString = dataSets[indexPath.row].docIDとすると
エラー:Fatal error: Index out of rangeとなります。
(どのセルをタップしてもエラーになります。)
numberOfRowsInSectionでは、
return dataSets.countとしてます。
なおその前にprintでdataSets.countを出力すると0ではなく, 適切な数字が出力されていました。
また、didSelectRowAt内でテスト出力してみると
firebaseからのデータを格納している構造体を格納する配列dastaSetsが空[]になっておりました。
indecPath.rowはクリックしたセルの番号が正しく出力されていました。
loadData()によって画面のセルにはFireStoreから読み込んだデータが読み込まれているのに、
dataSetsが[]である原因わかりません。
ご教示願います。
追記:
どうやらセルをタップした時に、loadData()が呼ばれているのか、if文のerror != nilの
print("erorrrrrr")が出力されたので、これによって、dataSetsが空のままになっていることがわかりました。
loadData()はviewWillAppearのみに記載しており、viewWillAppearは始めの画面生成時にのみよばれることから、セルタップ時にloadData()が呼ばれているのは
addSnapshotListnerのトリガーのようなものが関係しているのでしょうか。
あなたの回答
tips
プレビュー