迭代包含重复值的列表

时间:2018-01-25 04:55:37

标签: python python-2.7

我希望迭代一个包含重复值的列表。 101有101.A和101.B这是正确的但102开始于102.C而不是102.A

import string
room_numbers = ['101','103','101','102','104','105','106','107','102','108']
door_numbers = []
num_count = 0
for el in room_numbers:
    if room_numbers.count(el) == 1:
        door_numbers.append("%s.%s" % (el, string.ascii_uppercase[0]))
    elif room_numbers.count(el) > 1:
        door_numbers.append("%s.%s" % (el, string.ascii_uppercase[num_count]))
        num_count += 1

door_numbers = ['101.A','103.A','101.B','102.C','104.A',
                '105.A','106.A','107.A','102.D','108.A']   

4 个答案:

答案 0 :(得分:1)

<强>鉴于

import string
import itertools as it
import collections as ct


room_numbers = ['101','103','101','102','104','105','106','107','102','108']
letters = string.ascii_uppercase

<强>代码

简单的双线解决方案

dd = ct.defaultdict(it.count)    
print([".".join([room, letters[next(dd[room])]]) for room in room_numbers])

dd = ct.defaultdict(lambda: iter(letters))
print([".".join([room, next(dd[room])]) for room in room_numbers])

输出

['101.A', '103.A', '101.B', '102.A', '104.A', '105.A', '106.A', '107.A', '102.B', '108.A']

<强>详情

在第一个示例中,我们使用 itertools.count 作为default factory。这意味着只要将新的房间号添加到defaultdict count(),就会生成一个新的dd迭代器。迭代器很有用,因为它们被懒惰地评估并且内存有效。

在列表推导中,每个房间号都会初始化这些迭代器。产生下一个计数器的数字,该数字用作获取字母的索引,结果只是作为每个房间号的后缀加入。

在第二个例子(推荐)中,我们使用字符串的迭代器作为默认工厂。通过在lambda函数中返回迭代器来满足可调用的需求。字符串的迭代器使我们可以简单地调用next()并直接获取下一个字母。因此,简化了理解,因为不再需要切片letters

答案 1 :(得分:0)

天真的方式,只需计算元素在列表中包含的次数,直到该索引为止:

private void getData()

这两个显式的for循环使得二次复杂性突然出现。实际上,进行(1/2)*(N *(N-1))次迭代。我想说在大多数情况下,你最好保留>>> door_numbers = [] >>> for i in xrange(len(room_numbers)): ... el = room_numbers[i] ... n = 0 ... for j in xrange(0, i): ... n += el == room_numbers[j] ... c = string.ascii_uppercase[n] ... door_numbers.append("{}.{}".format(el, c)) ... >>> door_numbers ['101.A', '103.A', '101.B', '102.A', '104.A', '105.A', '106.A', '107.A', '102.B', '108.A'] 个计数,而不是每次计算。

dict

这样一来,索引就不会搞乱,而且时间效率更高(以辅助空间为代价)。

答案 2 :(得分:0)

您的实现中的问题是,您有一个值num_count,该值对于列表中的每个项目不断递增,而不仅仅是特定项目的计数。你需要做的是计算每个项目在列表中出现的次数。

伪代码将是 1.房间号码的每个房间 2.将房间添加到访问房间列表中 3.计算访问室中房间号码可用的次数 4.将计数添加到64并将其转换为ascii大写字符65=A 5.按照您希望的方式加入所需的字符串,然后将其附加到door_numbers列表。

这是一个实现

import string
room_numbers = ['101','103','101','102','104','105','106','107','102','108']
door_numbers = []

visited_rooms = []
for room in room_numbers:
    visited_rooms.append(room)
    room_count = visited_rooms.count(room)
    door_value = chr(64+room_count) # Since 65 = A when 1st item is present
    door_numbers.append("%s.%s"%(room, door_value))

door_numbers现在包含您期望的最终列表

['101.A', '103.A', '101.B', '102.A', '104.A', '105.A', '106.A', '107.A', '102.B', '108.A']

表示给定输入room_numbers

答案 3 :(得分:0)

使用迭代器和理解:

  1. 枚举房间以保留原始订单
  2. 按房间号码分组房间,根据groupby()
  3. 的要求排序
  4. 对于群组中的每个会议室,请附加.A.B等。
  5. 按步骤1中的枚举值排序以恢复原始订单
  6. 提取门号,例如&#39; 101.A&#39;
  7. #!/usr/bin/env python3
    
    import operator
    from itertools import groupby
    import string
    
    room_numbers = ['101', '103', '101', '102', '104',
                    '105', '106', '107', '102', '108']
    get_room_number = operator.itemgetter(1)
    enumerated_and_sorted = sorted(list(enumerate(room_numbers)),
                                   key=get_room_number)
    # [(0, '101'), (2, '101'), (3, '102'), (8, '102'), (1, '103'),
    #  (4, '104'), (5, '105'), (6, '106'), (7, '107'), (9, '108')]  
    grouped_by_room = groupby(enumerated_and_sorted, key=get_room_number)
    # [('101', [(0, '101'), (2, '101')]),
    #  ('102', [(3, '102'), (8, '102')]),
    #  ('103', [(1, '103')]),
    #  ('104', [(4, '104')]),
    #  ('105', [(5, '105')]),
    #  ('106', [(6, '106')]),
    #  ('107', [(7, '107')]),
    #  ('108', [(9, '108')])] 
    door_numbers = ((order, '{}.{}'.format(room, char))
                    for _, room_list in grouped_by_room
                    for (order, room), char in zip(room_list,
                                                   string.ascii_uppercase))
    # [(0, '101.A'), (2, '101.B'), (3, '102.A'), (8, '102.B'),
    #  (1, '103.A'), (4, '104.A'), (5, '105.A'), (6, '106.A'),
    #  (7, '107.A'), (9, '108.A')] 
    door_numbers = [room for _, room in sorted(door_numbers)]
    # ['101.A', '103.A', '101.B', '102.A', '104.A',
    #  '105.A', '106.A', '107.A', '102.B', '108.A']