简体   繁体   English

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

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

I want to re-write the function get_bs in a different way, how can I improve this nested for loop, may be in a more compact way? 我想以另一种方式重写函数get_bs,如何以更紧凑的方式改进此嵌套的for循环? Any suggestions? 有什么建议么?

I was thinking, may be split the nested loop in two different nested loops and each writing in one line, eg for i,j in.... Is this possible? 我当时在想,可以将嵌套循环分为两个不同的嵌套循环,每个循环写在一行中,例如对于i,j in ....这可能吗? Can someone please show me? 有人可以告诉我吗? Thanks. 谢谢。

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

Since you asked me how to do this in the comments... 由于您在评论中问我如何执行此操作...

To get i,j indices for a nested loop in a single line of code, using itertools: 使用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)

After that, have a separate for loop for the parts that only iterate over i. 之后,为仅迭代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))

Note, I don't think this is the best approach. 请注意,我认为这不是最好的方法。 Using Numpy and vector math would be much faster and more elegant. 使用Numpy和向量数学将更快,更优雅。

Usually, "no libraries" rules in assigments mean "Don't use an off the shelf implementation of the algorithm you're asked to implement". 通常,“无库”规则指的是“不要使用要求您实现的算法的现成实现”。 Not "Don't use any external convenience classes whatsoever". 不是“不要使用任何外部便利类”。

Maybe nobody dares to answer that you shouldn't always be looking further in changing your code, especially when it works. 也许没有人敢回答您在更改代码时不应该总是走得更远,尤其是在代码工作时。 Most important pieces of software are often redondant and unreadable because of repetition. 最重要的软件通常由于重复而难以编辑。 Just improve the functionnality or switch to a new software. 只需改善功能或切换到新软件即可。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM