Warning: file_get_contents(/data/phpspider/zhask/data//catemap/7/user-interface/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Python 将dict的一部分与副本合并_Python_Python 3.x - Fatal编程技术网

Python 将dict的一部分与副本合并

Python 将dict的一部分与副本合并,python,python-3.x,Python,Python 3.x,我是Python的初学者,所以请耐心听我说 我有一个目录,看起来像: list = [ { "name": "Bus 60", "direction": "City", "timeLeft": "1", "timeNext": "" }, { "name": "Bus 60", "direction": "City", "timeLeft": "3",

我是Python的初学者,所以请耐心听我说

我有一个目录,看起来像:

list = [
    {
        "name": "Bus 60",
        "direction": "City",
        "timeLeft": "1",
        "timeNext": ""
    },
    {
        "name": "Bus 60",
        "direction": "City",
        "timeLeft": "3",
        "timeNext": ""
    },
    {
        "name": "Bus 1",
        "direction": "Some Place",
        "timeLeft": "15",
        "timeNext": ""
    },
    {
        "name": "Bus 1",
        "direction": "Some Place",
        "timeLeft": "30",
        "timeNext": ""
    },
    {
        "name": "Bus 1",
        "direction": "That other place",
        "timeLeft": "5",
        "timeNext": ""
    },
]
我希望根据名称和方向将这两种情况合并,如下所示:

new_list = [
    {
        "name": "Bus 60",
        "direction": "City",
        "timeLeft": "1",
        "timeNext": "3"
    },
    {
        "name": "Bus 1",
        "direction": "Some Place",
        "timeLeft": "15",
        "timeNext": "30"
    },
    {
        "name": "Bus 1",
        "direction": "That other place",
        "timeLeft": "5",
        "timeNext": ""
    },
]
new_list = list(merge_busses(mylist))
我如何才能做到这一点,并了解它实际上是如何工作的? 我尝试过很多循环解决方案,但最终都会出现很多重复或错误的合并

编辑:每个名称和方向的副本不得超过一个

编辑2:这是我的完整方法:

@APP.route('/api/vasttrafik/departures', methods=['POST'])
def get_departures():
    """ Departures """
    APP.logger.info('get_departures():')

    data = request.get_json()
    id_number = data['id']
    current_date = date.today().strftime('%Y-%m-%d')
    current_time = datetime.now().strftime('%H:%M')
    # time_span = data['']
    access_token = request.headers['access_token']

    url = 'https://api.vasttrafik.se/bin/rest.exe/v2/departureBoard?id='\
        + id_number + '&date=' + current_date + '&time=' + current_time +\
        '&format=json&timeSpan=90&maxDeparturesPerLine=2&needJourneyDetail=0'
    headers = {'Authorization': 'Bearer ' + access_token}
    req = requests.get(url, headers=headers)
    json = req.json()
    departure_board = json['DepartureBoard']
    if 'error' in departure_board:
        raise NotFoundException('Did not find anything')
    departures = departure_board['Departure']

    def departures_model(item):

        def get_key_value(key):
            return item[key] if key in item else ''

        is_live = 'rtTime' in item
        if is_live:
            current_time = get_key_value('rtTime')
            current_date = get_key_value('rtDate')
        else:
            current_time = get_key_value('time')
            current_date = get_key_value('date')

        direction = get_key_value('direction')
        via = ''
        if 'via' in direction:
            direction, via = direction.split('via')

        time_departure = datetime.strptime(current_date + ' ' + current_time, '%Y-%m-%d %H:%M')
        time_now = datetime.now()
        diff = time_departure - time_now
        if time_now >= time_departure:
            minutes_left = 0
        else:
            minutes_left = math.floor(((diff).seconds) / 60)
        clock_left = item['rtTime'] if is_live else item['time']

        return dict({
            'accessibility': get_key_value('accessibility'),
            'bgColor': get_key_value('bgColor'),
            'clockLeft': clock_left,
            'clockNext': '',
            'timeLeft': int(minutes_left),
            'timeNext': '',
            'direction': direction.strip(),
            'via': 'via ' + via.strip() if via != '' else via,
            'name': get_key_value('name'),
            'sname': get_key_value('sname'),
            'type': get_key_value('type'),
            'time': get_key_value('time'),
            'date': get_key_value('date'),
            'journeyid': get_key_value('journeyid'),
            'track': get_key_value('track'),
            'fgColor': get_key_value('fgColor'),
            'isLive': is_live,
            'night': 'night' in item,
        })

    mapped_departures = list(map(departures_model, departures))

    def key(bus):
        return bus["name"], bus["direction"]

    def merge_busses(ls):
        for (name, direction), busses in groupby(ls, key):
            busses = list(busses)
            times = [bus["timeLeft"] for bus in busses]
            yield {
                **busses[0],
                "timeLeft": min(times, key=int),
                "timeNext": max(times, key=int),
            }

    merge_departures = list(merge_busses(mapped_departures))

    return jsonify({
        'departures': merge_departures,
    })

编辑3:我刚刚发现为什么L3viathan&Patrick Artner的解决方案不起作用。只有在预先对公交车列表进行排序的情况下,它们才起作用。所以我猜groupby需要dict相邻。

我的解决方案是:我们使用itertools.groupby按总线的名称-方向组合对总线进行分组,然后生成字典,其中timeLeft是这些总线中最小的分钟数,如果我们只看到一条总线,timeNext要么是一个空字符串,要么是这些总线中的最大分钟数

from itertools import groupby

def key(bus):
    return bus["name"], bus["direction"]

def merge_busses(ls):
    for (name, direction), busses in groupby(sorted(ls, key=key), key):
        busses = list(busses)
        times = [bus["timeLeft"] for bus in busses]
        yield {
            **busses[0],
            "timeLeft": min(times, key=int),
            "timeNext": "" if len(times) == 1 else max(times, key=int),
        }
像这样使用它:

new_list = [
    {
        "name": "Bus 60",
        "direction": "City",
        "timeLeft": "1",
        "timeNext": "3"
    },
    {
        "name": "Bus 1",
        "direction": "Some Place",
        "timeLeft": "15",
        "timeNext": "30"
    },
    {
        "name": "Bus 1",
        "direction": "That other place",
        "timeLeft": "5",
        "timeNext": ""
    },
]
new_list = list(merge_busses(mylist))
以您的示例为例,这将产生:

[
    {
        "name": "Bus 60",
        "direction": "City",
        "timeLeft": "1",
        "timeNext": "3"
    },
    {
        "name": "Bus 1",
        "direction": "Some Place",
        "timeLeft": "15",
        "timeNext": "30"
    },
    {
        "name": "Bus 1",
        "direction": "That other place",
        "timeLeft": "5",
        "timeNext": ""
    }
]

这是我的解决方案:我们使用itertools.groupby按名称方向组合对总线进行分组,然后生成字典,其中timeLeft是这些总线中最小的分钟数,而timeNext是空字符串(如果我们只看到一条总线),或者是这些总线中最大的分钟数

from itertools import groupby

def key(bus):
    return bus["name"], bus["direction"]

def merge_busses(ls):
    for (name, direction), busses in groupby(sorted(ls, key=key), key):
        busses = list(busses)
        times = [bus["timeLeft"] for bus in busses]
        yield {
            **busses[0],
            "timeLeft": min(times, key=int),
            "timeNext": "" if len(times) == 1 else max(times, key=int),
        }
像这样使用它:

new_list = [
    {
        "name": "Bus 60",
        "direction": "City",
        "timeLeft": "1",
        "timeNext": "3"
    },
    {
        "name": "Bus 1",
        "direction": "Some Place",
        "timeLeft": "15",
        "timeNext": "30"
    },
    {
        "name": "Bus 1",
        "direction": "That other place",
        "timeLeft": "5",
        "timeNext": ""
    },
]
new_list = list(merge_busses(mylist))
以您的示例为例,这将产生:

[
    {
        "name": "Bus 60",
        "direction": "City",
        "timeLeft": "1",
        "timeNext": "3"
    },
    {
        "name": "Bus 1",
        "direction": "Some Place",
        "timeLeft": "15",
        "timeNext": "30"
    },
    {
        "name": "Bus 1",
        "direction": "That other place",
        "timeLeft": "5",
        "timeNext": ""
    }
]

实现这一点的一种方法是按总线的名称和方向对所有总线进行分组。然后合并数据,确保较早的时间在“timeLeft”中,较晚的时间在“timeNext”中:

Doku:

输出:

[{'name': 'Bus 60', 'direction': 'City', 'timeLeft': '1', 'timeNext': '3'}, 
 {'name': 'Bus 21', 'direction': 'City', 'timeLeft': '5', 'timeNext': ''}]
您编辑的示例将导致:

[{'name': 'Bus 60', 'direction': 'City', 'timeLeft': '1', 'timeNext': '3'},
 {'name': 'Bus 1', 'direction': 'Some Place', 'timeLeft': '15', 'timeNext': '30'}, 
 {'name': 'Bus 1', 'direction': 'That other place', 'timeLeft': '5', 'timeNext': ''}]

实现这一点的一种方法是按总线的名称和方向对所有总线进行分组。然后合并数据,确保较早的时间在“timeLeft”中,较晚的时间在“timeNext”中:

Doku:

输出:

[{'name': 'Bus 60', 'direction': 'City', 'timeLeft': '1', 'timeNext': '3'}, 
 {'name': 'Bus 21', 'direction': 'City', 'timeLeft': '5', 'timeNext': ''}]
您编辑的示例将导致:

[{'name': 'Bus 60', 'direction': 'City', 'timeLeft': '1', 'timeNext': '3'},
 {'name': 'Bus 1', 'direction': 'Some Place', 'timeLeft': '15', 'timeNext': '30'}, 
 {'name': 'Bus 1', 'direction': 'That other place', 'timeLeft': '5', 'timeNext': ''}]


列表是否总是有两个元素和键?是的,它总是有这些键,但它可以有更多的dict。请提供一个有两个以上dict的示例,看看输出是什么样子,然后根据什么逻辑将3移动到另一个字段?使用dict UPDATE将列表始终有两个元素和这些键?是的,它将始终有这些键,但它可以有更多的dict。请提供一个包含两个以上dict的示例,以了解输出情况,那么根据什么逻辑将3移动到另一个字段?使用dictupdate@L3viathan我不太明白为什么我需要对它进行排序——分组可以在无序列表上工作——很好,组的键将确保在一个组中只有相同的总线。或者你的意思是完成后的输出顺序?我对此有与L3viathan的解决方案相同的问题。它不会合并我的公交车发车。不会,因为列表排序后,它现在可以工作了。你也可以在方法偏差模型中看到,所有DICT看起来都是一样的。这里我告诉过你:@PatrickArtner别担心,我真的认为groupby的实现就是这样的。不管怎么说,我很高兴它现在起作用了。谢谢你的帮助!剥离只是为了确保它不存在差异?@l3via然后我不太明白为什么我需要对它进行排序-分组在无序列表上工作很好,组的键将确保只有相同的总线在一个组中。或者你的意思是完成后的输出顺序?我对此有与L3viathan的解决方案相同的问题。它不会合并我的公交车发车。不会,因为列表排序后,它现在可以工作了。你也可以在方法偏差模型中看到,所有DICT看起来都是一样的。这里我告诉过你:@PatrickArtner别担心,我真的认为groupby的实现就是这样的。不管怎么说,我很高兴它现在起作用了。谢谢你的帮助!剥离只是为了确保它不存在差异?我没有通知您,我在dicts中还有其他需要的键/值。在您的第一个解决方案中,我可以使用**first[key]获取其他键,但在这个新解决方案中,我不确定如何执行该操作。bus未定义,因为它的作用域位于times变量内。我现在可以使用该代码获取重复项。我已经用文件中的全部内容更新了我的主要帖子。我没有收到你提供的例子的副本。给我一个更好的例子,我没有缩进来为这个设置一个烧瓶API。所以我是对的,你需要对它进行排序。已在编辑中修复。我未能通知您DICT中还有其他需要的键/值。在您的第一个解决方案中,我可以使用**first[key]获取其他键,但在这个新解决方案中,我不确定如何执行该操作。bus未定义,因为它的作用域位于times变量内。我现在可以使用该代码获取重复项。我已经用文件中的全部内容更新了我的主要帖子。我没有收到你提供的例子的副本。给我一个更好的例子,我不缩进来设置一个烧瓶API 您需要对其进行排序,这是正确的。在编辑中修复。