簡體   English   中英

我如何改善此嵌套的for循環?

[英]How can I improve this nested for loop?

我想以另一種方式重寫函數get_bs,如何以更緊湊的方式改進此嵌套的for循環? 有什么建議么?

我當時在想,可以將嵌套循環分為兩個不同的嵌套循環,每個循環寫在一行中,例如對於i,j in ....這可能嗎? 有人可以告訴我嗎? 謝謝。

class NB:
def __init__(self, train_data, test_data):
    self.train_data = train_data
    self.test_data = test_data
    self.train_entries = []
    self.test_entries = []
    self.diabetes_yes = []
    self.diabetes_no = []
    self.a_diabetesyes = []
    self.a_diabetesno = []
    self.b_diabetesyes = []
    self.b_diabetesno = []
    self.num_elements = 0
    self.p_diabetesyes = 0
    self.p_diabetesno = 0
    self.num_diabetesyes = 0
    self.num_diabetesno = 0

def trainNB(self):
    self.traincleandata()
    for i in range(self.num_elements - 1):
        self.a_diabetesyes[i] = sum(self.diabetes_yes[i]) / len(self.diabetes_yes[i])
        self.a_diabetesno[i] = sum(self.diabetes_no[i]) / len(self.diabetes_no[i])
    self.get_bs()

def traincleandata(self):
    for line in self.train_data:
        if self.num_elements == 0:
            self.num_elements = len(line.split(','))
            for i in range(self.num_elements):
                self.diabetes_yes.append([])
                self.diabetes_no.append([])
                self.a_diabetesyes.append(0.0)
                self.a_diabetesno.append(0.0)
                self.b_diabetesyes.append(0.0)
                self.b_diabetesno.append(0.0)
        params = line.split(',')
        cleanparams = getcleanparams(params)
        entry = Entry(cleanparams)
        self.train_entries.append(entry)

        for i in range(len(entry.elements) - 1):
            if (entry.diabetes == "yes"):
                self.diabetes_yes[i].append(Decimal(entry.elements[i]))
            else:
                self.diabetes_no[i].append(Decimal(entry.elements[i]))

        if (entry.diabetes == 'yes'):
            self.p_diabetesyes += 1
            self.num_diabetesyes += 1
        else:
            self.p_diabetesno += 1
            self.num_diabetesno += 1

    self.p_diabetesyes = Decimal(self.p_diabetesyes) / Decimal(len(self.train_entries))
    self.p_diabetesno = Decimal(self.p_diabetesno) / Decimal(len(self.train_entries))

def get_bs(self):

    sigSumYes = [0] * self.num_elements
    sigSumNo = [0] * self.num_elements

    for i in range(self.num_elements - 1):
        for j in range(self.num_diabetesyes):
            diff_yes = self.diabetes_yes[i][j] - self.a_diabetesyes[i]
            sigSumYes[i] += m.pow(diff_yes, 2)
        self.b_diabetesyes[i] = m.sqrt(sigSumYes[i] / (len(self.diabetes_yes[i]) - 1))
        for j in range(self.num_diabetesno):
            diff_no = self.diabetes_no[i][j] - self.a_diabetesno[i]
            sigSumNo[i] += m.pow(diff_no, 2)
        self.b_diabetesno[i] = m.sqrt(sigSumNo[i] / (len(self.diabetes_no[i]) - 1))

def testNB(self):
    self.testcleandata()
    self.testalgo()

def testcleandata(self):
    for line in self.test_data:
        params = line.split(',')
        cleanparams = getcleanparams(params)
        entry = Entry(cleanparams)
        self.test_entries.append(entry)

def testalgo(self):
    counter = 1
    P_diabetesyes = [0] * self.num_elements
    P_diabetesno = [0] * self.num_elements
    for entry in self.test_entries:
        pYesEntry = 1
        pNoEntry = 1
        pYesEntry, pNoEntry = self.test_Entry(pYesEntry, pNoEntry, P_diabetesyes, P_diabetesno, entry)

        pYesEntry *= float(self.p_diabetesyes)
        pNoEntry *= float(self.p_diabetesno)

        entry.set_ifdiabetes("yes") if (pYesEntry / pNoEntry >= 1) else entry.set_ifdiabetes("no")
        counter += 1

def test_Entry(self, pYesEntry, pNoEntry, P_diabetesyes, P_diabetesno, entry):
    for i in range(self.num_elements - 1):
        P_diabetesyes[i] = Decimal((1 / (self.b_diabetesyes[i] * m.sqrt(2 * m.pi))) * m.pow(m.e, (
                -m.pow(Decimal(entry.elements[i]) - self.a_diabetesyes[i], 2) / (
                2 * m.pow(self.b_diabetesyes[i], 2)))))
        P_diabetesno[i] = Decimal((1 / (self.b_diabetesno[i] * m.sqrt(2 * m.pi))) * m.pow(m.e, (
                -m.pow(Decimal(entry.elements[i]) - self.a_diabetesno[i], 2) / (
                2 * m.pow(self.b_diabetesno[i], 2)))))
        pYesEntry *= float(P_diabetesyes[i])
        pNoEntry *= float(P_diabetesno[i])

    return pYesEntry, pNoEntry

由於您在評論中問我如何執行此操作...

使用itertools在單行代碼中獲得嵌套循環的i,j索引:

import itertools

for i, j in itertools.product(range(self.num_elements - 1),
                              range(self.num_diabetesyes)):
    diff_yes = self.diabetes_yes[i][j] - self.a_diabetesyes[i]
    sigSumYes[i] += m.pow(diff_yes, 2)

    diff_no = self.diabetes_no[i][j] - self.a_diabetesno[i]
    sigSumNo[i] += m.pow(diff_no, 2)

之后,為僅迭代i的部分設置單獨的for循環。

for i in range(self.num_elements - 1):
    self.b_diabetesyes[i] = m.sqrt(sigSumYes[i] / (len(self.diabetes_yes[i]) - 1))
    self.b_diabetesno[i] = m.sqrt(sigSumNo[i] / (len(self.diabetes_no[i]) - 1))

請注意,我認為這不是最好的方法。 使用Numpy和向量數學將更快,更優雅。

通常,“無庫”規則指的是“不要使用要求您實現的算法的現成實現”。 不是“不要使用任何外部便利類”。

也許沒有人敢回答您在更改代碼時不應該總是走得更遠,尤其是在代碼工作時。 最重要的軟件通常由於重復而難以編輯。 只需改善功能或切換到新軟件即可。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM