【问题标题】:for loop & if in a dictionaryfor 循环和 if 在字典中
【发布时间】:2016-02-21 14:18:18
【问题描述】:

注意:我是 Python 新手。

我的任务是设计一个程序,该程序将从 10 个车牌列表(英国和外国车牌的混合)中输出 外国 车牌,但前提是它们正在超速行驶。在此过程中我犯了一些错误,我不确定如何解决这些问题。 #UK 和 #F 只是我的笔记,让我能够快速查看哪个是英国车牌,哪个是外国车牌。

import re

distance=750 #variable for the distance between the Camera A and B (in m)
speedlimit=60 # (mps)
NumberPlates=["DV61 GGB",#UK
              "D3S11 EUBG 20",#F
              "5T314 10A02",#F
              "24TEG 5063",#F
              "TR09 TRE",#UK
              "524 WAL 75",#F
              "TR44 VCZ",#UK
              "FR52 SWD",#UK
              "100 GBS 12",#F
              "HG55 BPO"#UK
              ]

Enter=[7.12,7.17,7.20,7.45,7.23,7.33,7.18,7.25,7.33,7.38]
#A list for the times of cars passing Camera A
Leave=[7.56,7.24,7.48,7.52,7.45,7.57,7.22,7.31,7.37,7.47]
#A list for the times of cars passing Camera B

Timestaken=[]
Timestaken2=[]
Timestaken3={}

for enter_data, leave_data in zip(Enter, Leave):
    Timestaken.append(leave_data-enter_data)

Timestaken=["%.2f" % (leave_data-enter_data) for enter_data, leave_data in zip(Enter, Leave)]
Timestaken2=[s.strip("0") for s in Timestaken]
Timestaken2=[s.strip('.') for s in Timestaken2]

for key,value in zip(NumberPlates,Timestaken2):
    Timestaken3[key]=value

print(Timestaken3)

for item in NumberPlates:
    UK_Numbers=list(filter(lambda x: re.match("[A-Z]{2}\d{2}\s+[A-Z]{3}$",x),NumberPlates))
    for item in UK_Numbers:
        if item in UK_Numbers:
            NumberPlates.remove(item)

print(NumberPlates) #These are foreign number plates only.

Timestaken4={}

for key,value in zip(NumberPlates,Timestaken2):
    Timestaken4[key]=value

print(Timestaken4) #NumberPlate:Time

print("10 cars have passed Camera A, then Camera B\n")

for key,value in Timestaken4.items():
    speed=distance/int(value)
    if speed>speedlimit:
        print(key,"is speeding with",distance/int(value),"mps")

我得到这个输出:

>>> 
{'5T314 10A02': '28', '100 GBS 12': '04', '524 WAL 75': '24', 'D3S11 EUBG 20': '07', '24TEG 5063': '07', 'HG55 BPO': '09', 'TR44 VCZ': '04', 'TR09 TRE': '22', 'DV61 GGB': '44', 'FR52 SWD': '06'}
['D3S11 EUBG 20', '5T314 10A02', '24TEG 5063', '524 WAL 75', '100 GBS 12']
{'5T314 10A02': '07', '100 GBS 12': '22', '524 WAL 75': '07', '24TEG 5063': '28', 'D3S11 EUBG 20': '44'}
10 cars have passed Camera A, then Camera B

5T314 10A02 is speeding with 107.14285714285714 mps
524 WAL 75 is speeding with 107.14285714285714 mps

最后两条线应该有不同的速度。我意识到进入和离开时间导致的速度是不人道的,但这不是我遇到的问题。

第三个输出行显示时间分配给不同的车牌。我正在寻找解决此问题的方法。

最后两行输出与:

for key,value in Timestaken4.items():
    speed=distance/int(value)
    if speed>speedlimit:
        print(key,"is speeding with",distance/int(value),"mps")

除了分配给不同车牌的时间之外,如何修改代码以显示正确的速度?

【问题讨论】:

    标签: python python-3.x if-statement for-loop dictionary


    【解决方案1】:

    你可以这样做:

    import re
    
    # DATA
    distance = 750 # Distance between the Camera A and B (in m)
    speed_limit = 60 # (mps)
    
    number_plates = ["DV61 GGB",      #UK
                     "D3S11 EUBG 20", #F
                     "5T314 10A02",   #F
                     "24TEG 5063",    #F
                     "TR09 TRE",      #UK
                     "524 WAL 75",    #F
                     "TR44 VCZ",      #UK
                     "FR52 SWD",      #UK
                     "100 GBS 12",    #F
                     "HG55 BPO"       #UK
                     ]
    
    enter = [7.12,7.17,7.20,7.45,7.23,7.33,7.18,7.25,7.33,7.38]
    leave = [7.56,7.24,7.48,7.52,7.45,7.57,7.22,7.31,7.37,7.47]
    
    # Find the non-UK plates
    pattern = "(?![A-Z]{2}\d{2}\s+[A-Z]{3}$)"
    foreign_numbers = list(filter(lambda x: re.match(pattern, x), number_plates))
    
    # Compute speeds
    elapsed = [l - e for l, e in zip(leave, enter)]
    speed = [distance/t for t in elapsed]
    
    # Conditional dictionary comprehension
    foreign_speeders = {plate: speed 
                        for plate, speed in zip(number_plates, speed)
                        if (plate in foreign_numbers) and (speed > speed_limit)}
    
    foreign_speeders
    

    这给出了:

    {'100 GBS 12': 18749.99999999998,
     '24TEG 5063': 10714.285714285807,
     '524 WAL 75': 3124.9999999999973,
     '5T314 10A02': 2678.571428571426,
     'D3S11 EUBG 20': 10714.28571428567}
    

    你可以格式化:

    for plate, speed in foreign_speeders.items():
        print("{0:>14s}  was speeding at {1:8.1f} m/s".format(plate, speed))
    

    这些单位看起来很古怪。我的猜测是,限速实际上是英里每小时。顺便说一句,如果是我并且有很多数据,我可能会在 pandas 或者至少是 NumPy ......那么你不必那么小心地将所有这些列表保持在正确的顺序和合适的长度。但是这些乐趣可以等到您看到更多 Python 之后。

    【讨论】:

    • 我尝试以英里/小时为单位工作,但对我来说并不奏效。我转换了所有值,以便它们适合米/秒单位,但是有没有办法将经过的时间四舍五入?在elapsed = [l - e for l, e in zip(leave, enter)] 之后,我收到了诸如D3S11 EUBG 20 was speeding at 2727.3 mps 之类的结果,结果应该是27.2727 等。抱歉,如果这是个问题,我还在弄清楚你的代码。
    • 而不是 l-e(l-e)/100 放在该列表理解中。也许distance 的单位是厘米?或者时间是分钟......
    • 我想通了,但(l-e)/100 也很有帮助。最后,您能否向我解释一下("{0:>14s} was speeding at {1:8.1f} m/s".format(plate, speed)) 的作用?这是我第一次遇到这样的方法,我的部分任务是解释代码的每个部分。我希望你明白。提前致谢!
    • 阅读string formatting... 我认为这比我在这里解释得更好。我建议在 REPL 中使用它。
    • 这为我解释了。再次非常感谢您的帮助!
    【解决方案2】:

    这是我的解决方法

    from datetime import datetime
    
    
    distance = 750
    speed_limit = 60
    
    camera_a = {
        "DV61 GGB": 7.12,
        "D3S11 EUBG 20": 7.17,
        }
    
    camera_b = {
        "DV61 GGB": 7.56,
        "D3S11 EUBG 20": 7.24,
        }
    
    
    def velocity(a, b):
        entry = datetime.strptime(str(a), '%M.%S')
        exit = datetime.strptime(str(b), '%M.%S')
        elapsed_time_in_seconds = (exit - entry).total_seconds()
        velocity_mph = (distance / elapsed_time_in_seconds) / (1609.44/3600)
    
        return velocity_mph
    
    for number_plate, t in camera_a.iteritems():
        if number_plate in camera_b.keys():
            velocity_mph = velocity(t, camera_b[number_plate])
    
            if velocity_mph > speed_limit:
                print '%s was speeding: %.2f mp/h' % (number_plate, velocity_mph)
    

    首先,我会使用字典而不是列表来存储来自摄像机的数据。这使事情变得更容易(如果其中一辆车超过另一辆车并弄乱了您的列表顺序,您不会有问题)。我不需要单独的车牌列表,因为我可以使用 camera_a-dictionary 中的键

    然后我将遍历相机 A 的键/值对,检查车牌是否是两个字典中的键(如果相机 B 中缺少它,则意味着汽车位于相机之间或使用过下车的出口)。

    速度函数将相机 A 和 B 的值转换为日期时间对象。我假设这些值是 Minute.Second 格式并以 mp/h 为单位返回汽车的速度

    最后,我们检查汽车的行驶速度是否超过了限速并打印出一条消息。

    在我的示例中,我没有解决您的最后一个标准(“输出外国车牌”)。为此,我将创建第二个名为“is_foreign”的函数,该函数将车牌作为输入,并返回 True/False

    【讨论】:

    • 这适用于 Python 2.7 吗?
    • 是的。 (昨天简化时我在答案中留下了一个愚蠢的错误。我已更正错误并在 python 2.7.10 上对其进行了测试)。
    猜你喜欢
    • 2017-07-21
    • 2014-07-18
    • 1970-01-01
    • 2022-11-17
    • 1970-01-01
    • 2021-07-30
    • 2022-01-04
    • 2023-03-20
    • 1970-01-01
    相关资源
    最近更新 更多