【问题标题】:Rearranging elements in Python在 Python 中重新排列元素
【发布时间】:2019-04-23 20:15:07
【问题描述】:

我是 Python 新手,但我无法得到这个。我有一个列表,我想从那里获取输入并将其写入文件中。

p = ['Eth1/1', 'Eth1/5','Eth2/1', 'Eth2/4','Eth101/1/1', 'Eth101/1/2', 'Eth101/1/3','Eth102/1/1', 'Eth102/1/2', 'Eth102/1/3','Eth103/1/1', 'Eth103/1/2', 'Eth103/1/3','Eth103/1/4','Eth104/1/1', 'Eth104/1/2', 'Eth104/1/3','Eth104/1/4']

我正在尝试什么:

with open("abc1.txt", "w+") as fw1, open("abc2.txt", "w+") as fw2:
for i in p:
    if len(i.partition("/")[0]) == 4:
        fw1.write('int ' + i + '\n  mode\n')
    else:
        i = 0
        while i < len(p):
            start = p[i].split('/')
            if (start[0] == 'Eth101'):
                i += 3

            key = start[0]
            i += 1
            while i < len(p) and p[i].split('/')[0] == key:
                i += 1
            end = p[i-1].split('/')
            fw2.write('confi ' + start[0] + '/' + start[1] + '-' + end[1] + '\n mode\n')

我在寻找什么:

abc1.txt 应该有

int Eth1/1
  mode
int Eth1/5
  mode
int Eth2/1
  mode
int Eth 2/4
  mode

abc2.txt 应该有:

int Eth101/1/1-3
  mode
int Eth102/1/1-3
  mode
int Eth103/1/1-4
  mode
int Eth104/1/1-4
  mode
  1. 所以任何在“/”之前有 1 位数字的 Eth(例如:Eth1/1 或 Eth2/2 ) 应位于 abc1.txt 文件中。

  2. “/”前有 3 位数字的任何 Eth(例如:Eth101/1/1 或 Eth 102/1/1 ) 应该在另一个文件中,即 abc2.txt 和 .As 这些文件中 范围,需要像Eth101/1/1-3,Eth102/1/1-3等这样写

有什么想法吗?

【问题讨论】:

  • 您只打开了一个文件用于写入。您是否尝试过以写入模式打开两个文件?
  • @colidyre 我更新我的问题
  • @colidyre 嘿,我用我正在尝试的内容更新了我的问题..我没有得到想要的结果..知道我需要怎么做吗?
  • @colidyre: 我收到 def get_network_ranges(networks: list:) 的错误“无效语法”
  • 此评论最好放在答案中。但是:您有一个不支持类型提示的较旧的 python 版本。只需删除def get_network_ranges(networks): 的类型提示啊,抱歉监督了您的 Python 版本。 2.6 :/

标签: list python-2.6


【解决方案1】:

我认为您根本不需要正则表达式。您的所有项目都以“Eth”开头,后跟一位或多位数字。因此,您可以在第一次出现 / 之前检查项目的长度,然后将其写入文件。

p = ['Eth1/1', 'Eth1/5','Eth2/1', 'Eth2/4','Eth101/1/1', 'Eth101/1/2', 'Eth101/1/3','Eth102/1/1', 'Eth102/1/2', 'Eth102/1/3','Eth103/1/1', 'Eth103/1/2', 'Eth103/1/3','Eth103/1/4','Eth104/1/1', 'Eth104/1/2', 'Eth104/1/3','Eth104/1/4']

with open("abc1.txt", "w+") as fw1, open("abc2.txt", "w+") as fw2:
    for i in p:
        if len(i.partition("/")[0]) == 4:
            fw1.write('int ' + i + '\n  mode\n')
        else:
            fw2.write('int ' + i + '\n  mode\n')

我稍微重构了您的代码以使with-statement 发挥作用。这将在最后正确关闭文件。此外,不需要对序列进行两次迭代,因此只需一次迭代即可完成。

如果数据不像提供的那样干净,那么您可能想要使用正则表达式。独立于正则表达式本身,通过编写if re.match(r'((Eth\d{1}\/\d{1,2})', "p" ),您可以证明是否可以为字符串"p" 上的给定正则表达式创建匹配对象,而不是变量p 的值。这是因为您在p 周围使用了"

所以这应该适用于您的示例。如果你真的需要一个正则表达式,这将解决你寻找一个好的正则表达式来满足你的需要而没有任何其他问题的问题。

由于这些都在范围内,需要像 Eth101/1/1-3、Eth102/1/1-3 等这样写

这是您可以通过首先计算字符串然后将其写入文件来实现的。但这更像是一个单独的问题。

更新

计算正确的网络范围并非易事。在这里,我可以向您展示一种不会更改我的代码但会添加一些功能的方法。这里的诀窍是获得不会被其数量中断的连接网络组。为此,我复制了consecutive_groups。当然,您也可以通过pip install more-itertools 获得该功能。我还将列表转换为 dict 以准备魔法,然后将 dict 重新转换为列表。肯定有更好的方法,但这至少适用于您的输入数据。

#!/usr/bin/env python3
# -*- coding: utf-8 -*-

from itertools import groupby
from operator import itemgetter

p = ['Eth1/1', 'Eth1/5', 'Eth2/1', 'Eth2/4', 'Eth101/1/1', 'Eth101/1/2',
     'Eth101/1/3', 'Eth102/1/1', 'Eth102/1/2', 'Eth102/1/3', 'Eth103/1/1',
     'Eth103/1/2', 'Eth103/1/3', 'Eth103/1/4', 'Eth104/1/1', 'Eth104/1/2',
     'Eth104/1/3', 'Eth104/1/4']


def get_network_ranges(networks):
    network_ranges = {}
    result = []

    for network in networks:
        parts = network.rpartition("/")
        network_ranges.setdefault(parts[0], []).append(int(parts[2]))

    for network, ranges in network_ranges.items():
        ranges.sort()
        for group in consecutive_groups(ranges):
            group = list(group)
            if len(group) == 1:
                result.append(network + "/" + str(group[0]))
            else:
                result.append(network + "/" + str(group[0]) + "-" +
                              str(group[-1]))

    result.sort()  # to get ordered results
    return result


def consecutive_groups(iterable, ordering=lambda x: x):
    """taken from more-itertools (latest)"""
    for k, g in groupby(
        enumerate(iterable), key=lambda x: x[0] - ordering(x[1])
    ):
        yield map(itemgetter(1), g)


# only one line added to do the magic
with open("abc1.txt", "w+") as fw1, open("abc2.txt", "w+") as fw2:
    p = get_network_ranges(p)
    for i in p:
        if len(i.partition("/")[0]) == 4:
            fw1.write('int ' + i + '\n  mode\n')
        else:
            fw2.write('int ' + i + '\n  mode\n')

【讨论】:

    猜你喜欢
    • 2016-01-20
    • 2019-06-24
    • 1970-01-01
    • 2023-01-27
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-05-08
    相关资源
    最近更新 更多