重写循环以将数字分配给列中的每一行

2024-09-28 05:42:46 发布

您现在位置:Python中文网/ 问答频道 /正文

我有一个标题为CompanyNam的列,需要提取所有权信息。列位于QGIS属性表中,但这并不重要。该列看起来像所附图片。你知道吗

enter image description here

例如,如果CEZ是第一个公司,那么我给它分配数字1,然后Sokolovska是下一个数字,等等。如果CEZ再次出现在其他行中,它将得到数字1。需要注意的是,如果我在列中有NULL,我会为每个空行条目分配一个不同的数字。我需要与CompanyNam输出相对应的数字。我有以下代码:

EmptyArray = []
d = {}
newlist = []
for gFeat in GeneratorLayer.getFeatures():
    Owner = gFeat.attributes()[gProvider.fieldNameIndex('CompanyNam')].toString()
    A = ([str(i) for i in Owner]) #convert from PyQt4.QtCore.QString to normal string
    B = ''.join(A)
    EmptyArray.append(B)
    for m, n in enumerate(EmptyArray):
        if n not in d:
            d[n] = [m+1]
        newlist.append({n: d[n]})
        if n == '':
            d[n] = [m+1]
        newlist.append({n: d[n]}) #Every NULL gets a new number
    for names in newlist:
        for o, p in names.iteritems():
            if o == '':
                a2 = str('{},NULL'.format(p))
            elif o != '':
                a2 = str('{},{}'.format(p,o))

然后在进一步的步骤中使用a2。对于60-100行的列,代码运行良好,但是对于较大的列,计算时间非常长。你能建议我用什么方法重新编写代码,保持逻辑吗? 输出如下所示:

[1],CEZ
[1],CEZ
[1],CEZ
[1],CEZ
[1],CEZ
[1],CEZ
[1],CEZ
[1],CEZ
[9],Sokolovska
[10],International
[11],ENERGOTRANS,
[12],Alpiq
[13],Mittal Steel
[14],United
[1],CEZ
[1],CEZ
[17],Dalkia.....

如果有编号[1 ], [2], [3]而不是[1 ], [9], [10]就更好了,但我还不知道怎么做。你知道吗


Tags: 代码ina2forif数字nullappend
1条回答
网友
1楼 · 发布于 2024-09-28 05:42:46

我将使用一个列表,就像您附加项目一样,并使用一个单独的字典来获取数字:

EmptyArray = []
d = {}
newlist = []

for gFeat in GeneratorLayer.getFeatures():

    Owner = gFeat.attributes()[gProvider.fieldNameIndex('CompanyNam')].toString()

    A = ([str(i) for i in Owner]) #convert from PyQt4.QtCore.QString to normal string
    B = ''.join(A)

    EmptyArray.append(B)

    m = 1

    for n in EmptyArray:  # no need to enumerate as numbers should increment only on uniques

        if n not in d:  # this is a unique
            d[n] = [m]  # put number in dictionary, with key as val.
            m += 1  # so increment

        elif n == '':  # if it's blank (and if it is already in the dict)
            d[n].append(m)  # append new number, as blanks always increment
            m += 1  # increment

    for name in EmptyArray:  # looping less as only want to get names

        if name == '':  # if it's a blank, we want to pop out the first item in the list.
            a2 = str('{},NULL'.format(d[name].pop(0)))

        else:  # otherwise we just index the first item.
            a2 = str('{},{}'.format(d[name][0], name))

以上这些应该是有效的。你知道吗

这样你就不必循环太多,逻辑就更清晰了。这可能会有助于计算时间,但也会给你正确的数字。你知道吗

我们总是在通过空数组循环时附加到一个列表,这可能不是最好的方法,因为您只需要一个空白的列表,直接访问一个项目而不使用列表会更快-但当列表是1个项目长我怀疑会有很大的不同。你知道吗

对于空格,我们需要使用一个列表,这样它就可以接受多个数字(每个空格一个)。要为每个空格获取正确的数字,我们只需在每次遇到空格时从列表的前面弹出数字-该数字应与最初分配给该空格的数字相对应。你知道吗

我们也不需要建立一个新的列表,只需在EmptyArray上重复我们的循环即可。你知道吗

使之更有效

我们可以完全去掉EmptyArray上的第二个循环(我看不出有任何额外的逻辑需要这样做),只需对第一个循环执行以下操作:

    for n in EmptyArray:  # no need to enumerate as numbers should increment only on uniques

        if n == '' :  # blanks always increment - no need to store as we treat them as new
            a2 = str('{},NULL'.format(m))
            m += 1  # so increment

        elif n not in d:  # this is unique, so add to dict and increment
            d[n] = m  # add to dict for future reference
            a2 = str('{},{}'.format(m, n))
            m += 1  # increment

        else:  # it's in the dict, and not a blank, so grab from dict.
            a2 = str('{},{}'.format(d[n], n))

这样我们就去掉了大量的循环,程序的效率应该大大提高。它还消除了存储空白对应数字的需要,这样就节省了额外的工作——我们可以直接引用数字来处理其他事情。你知道吗

所以我做了两个函数来复制你想要的东西:

EmptyArray = ['',1,2,3,'',1,'',3,2,'',1]
m = 1
a2 = ''

def f1 (EmptyArray, d, m, a2):
    for n in EmptyArray:  # no need to enumerate as numbers should increment only on uniques

        if n not in d:  # this is a unique
            d[n] = [m]  # put number in dictionary, with key as val.
            m += 1  # so increment

        elif n == '':  # if it's blank (and if it is already in the dict)
            d[n].append(m)  # append new number, as blanks always increment
            m += 1  # increment

    for name in EmptyArray:  # looping less as only want to get names

        if name == '':  # if it's a blank, we want to pop out the first item in the list.
            a2 += str('{},NULL\n'.format(d[name].pop(0)))

        else:  # otherwise we just index the first item.
            a2 += str('{},{}\n'.format(d[name][0], name))

    print(a2)

def f2 (EmptyArray, d, m, a2):
    for n in EmptyArray:  # no need to enumerate as numbers should increment only on uniques

        if n == '' :  # blanks always increment - no need to store as we treat them as new
            a2 += str('{},NULL\n'.format(m))
            m += 1  # so increment

        elif n not in d:  # this is unique, so add to dict and increment
            d[n] = m  # add to dict for future reference
            a2 += str('{},{}\n'.format(m, n))
            m += 1  # increment

        else:  # it's in the dict, and not a blank, so grab from dict.
            a2 += str('{},{}\n'.format(d[n], n))

    print(a2)

f1(EmptyArray, {}, m, a2)
f2(EmptyArray, {}, m, a2)

以下是调用的输出:

1,NULL
2,1
3,2
4,3
5,NULL
2,1
6,NULL
4,3
3,2
7,NULL
2,1

1,NULL
2,1
3,2
4,3
5,NULL
2,1
6,NULL
4,3
3,2
7,NULL
2,1

f1和f2的时间分别为:

3.4341892885662415e-05
1.5789376039385022e-05

所以f2的时间比f1少了一半。你知道吗

相关问题 更多 >

    热门问题