我扩展并添加了一个新问题。
我有一个清单:
li = [2, 3, 1, 4, 2, 2, 2, 3, 1, 3, 2]
然后我会识别哪个值最常出现,我在变量i2
中保留哪个值:
f = {}
for item in li:
f[item] = f.get(item, 0) + 1
for i in f:
if f[i]==int(max(f.values())):
i2 = i
稍后重复的所有值都会增加10,但除了最大值之外。这是我使用的代码:
for i in range(len(li)):
for x in range(i + 1, len(li)):
if li[i] == li[x] and li[i] != i2:
li[x] = li[x] + 10
在此操作之后,我得到:
li = [2, 3, 1, 4, 2, 2, 2, 13, 11, 23, 2]
如您所见,最常见的值是2,因此它保持不变。例如,3发生三次,并且从所有三个新值创建3,3 + 10,3 + 20.并且与值的其余部分相同(除了2)。 但是如果两个最大值彼此相邻(或者在更长的序列中),我想逐个增加这个序列中的每个后续值,并得到:
li = [2, 3, 1, 4, 2, 12, 22, 13, 11, 23, 2]
怎么做?
我现在可以在新循环上执行相同的操作,但已经在更改的列表上并应用条件li[i] == li[i+1]
,但也许可以在当前循环中完成?
答案 0 :(得分:5)
首先,您应该使用collections.Counter
来获取列表中元素的计数并找到most_common
元素。
li = [2, 3, 1, 4, 2, 2, 2, 3, 1, 3, 2]
l2 = collections.Counter(li).most_common(1)[0][0]
然后,如果当前元素是最常见元素的第一个匹配项,则可以使用第二个Counter
作为运行计数,并将其重置为0
。然后使用该计数器将10的倍数加到数字上,然后递增它。
running = collections.Counter()
last = None
for i, e in enumerate(li):
if e == l2 and e != last:
running[e] = 0
li[i] = e + 10 * running[e]
running[e] += 1
last = e
之后,li
为[2, 3, 1, 4, 2, 12, 22, 13, 11, 23, 2]
答案 1 :(得分:2)
以下是嵌套循环的一个块中的解决方案:
import numpy as np
from collections import Counter
li = [2, 3, 1, 4, 2, 2, 2, 3, 1, 3, 2]
#Get most common
i2=Counter(li).most_common()[0][0]
for val in set(li): #loop over all unique values in li
inds=np.where([i==val for i in li])[0] #get array of indices where li==val
#special case for i2:
if val==i2:
c=1
for ind in range(1,len(inds)):
if inds[ind]==inds[ind-1]+1:
li[inds[ind]]=li[inds[ind]]+10*c
c+=1
else:
c=1
#not i2:
else:
c=1
for ind in range(1,len(inds)):
li[inds[ind]]=li[inds[ind]]+10*c
c+=1
它返回:
print(li)
[2, 3, 1, 4, 2, 12, 22, 13, 11, 23, 2]
一步一步演练:
计数器是获取i2的一种快捷方式,我们想要零元素,它是列表中最常见元素的值(不是计数)。
然后循环遍历列表中的所有唯一值,首先获取列表中的li与值相等的索引。
然后如果val==i2
它将乘数c
初始化为1并且循环检查连续索引(NB。此循环从1开始,所以任何val的第一次出现从未触及),如果发现它增加乘数和li中的值,如果不是连续索引,则将乘数重置为1。
对于所有其他值,它只是循环索引(再次从第二个)增加值和乘数
答案 2 :(得分:1)
我希望我的问题是正确的。这是:
from collections import Counter
def fix_pivot(my_list, max_el):
new_list = []
inc = 0
for item in my_list:
if item == max_el:
new_list.append(item + inc)
inc += 10
else:
new_list.append(item)
inc = 0
return new_list
li = [2, 3, 1, 4, 2, 2, 3, 1, 3, 2]
counted_li = Counter(li)
pivot = counted_li.most_common(1)[0][0]
# operating on all elements except for the most frequent, see note 1
temp = {k:[k + 10*(v-i-1) for i in range(v)] for k, v in counted_li.items()}
new = [temp[k].pop() if k != pivot else k for k in li]
# operating on the most frequent element, see note 2
res = fix_pivot(new, pivot)
print(res) # -> [2, 3, 1, 4, 2, 12, 13, 11, 23, 2]
注意:
根据原始列表li
中元素的频率,创建一个如下所示的字典(temp
):
{2: [32, 22, 12, 2], 3: [23, 13, 3], 1: [11, 1], 4: [4]}
结合[temp[k].pop() if k != pivot else k for k in li]
列表理解,它会产生一个非常(至少爱,pop
动作)优雅的方式来获得要求的第一部分;递增所有不是最常见的元素。
对于第二个,奇怪的要求,最简洁的方法是使用一个函数(再次imo)。每次函数遇到最常见的元素时,它会递增增量(0 - > 10 - > 20),每次找到不同的元素时,它会将其重置为0.
答案 3 :(得分:1)
这是我的答案,但我认为tobias_k的答案是最优雅的。
from collections import Counter
li = [2, 3, 1, 4, 2, 2, 3, 1, 3, 2]
c = Counter(li)
mc = max(c, key=c.get)
mapper = {k: 0 for k in li}
out = []
for i, v in enumerate(li):
if v == mc:
if i > 0 and li[i - 1] == mc:
mapper[v] += 10
out.append(v + mapper[v])
else:
mapper[v] = 0
out.append(v)
else:
out.append(v + mapper[v])
mapper[v] += 10
print(out)
>>> [2, 3, 1, 4, 2, 12, 13, 11, 23, 2]