Python 如何在单个值中转换带有连字符和逗号的数字范围列表

Python 如何在单个值中转换带有连字符和逗号的数字范围列表,python,excel,text,Python,Excel,Text,我有一个数字列表,格式如下所示: 3074 88, 3074 1935, 3478-3480 3074, 3478-3479 27015-27030, 27036-27037 4380, 27000-27031, 27036 基本上,这是端口和端口间隔的集合。 我想将此列表转换为一维数组,例如: 3074 88 3074 1935 3478 3479 3480 ... 基本上,我想要一个单独的列,但是要有重复的值,以便保留关于列表中显示的数字频率的信息 我更愿意在Excel或Python中执

我有一个数字列表,格式如下所示:

3074
88, 3074
1935, 3478-3480
3074, 3478-3479
27015-27030, 27036-27037
4380, 27000-27031, 27036
基本上,这是端口和端口间隔的集合。 我想将此列表转换为一维数组,例如:

3074
88
3074
1935
3478
3479
3480
...
基本上,我想要一个单独的列,但是要有重复的值,以便保留关于列表中显示的数字频率的信息

我更愿意在Excel或Python中执行此操作

你有什么建议吗


谢谢

您可以使用嵌套for循环:

f = """
     3074
88, 3074
1935, 3478-3480
3074, 3478-3479
27015-27030, 27036-27037
4380, 27000-27031, 27036 """

l = []
for x in f.split('\n'):
    for y in x.split(','):
        l += [z.strip() for z in y.split('-')]

for x in l:
    print(x)
>>
3074
88
3074
1935
3478
3480
3074
3478
3479
27015
27030
27036
27037
4380
27000
27031
27036
当然,如果这是一个文件,请使用

with open("filename.txt") as f:
    l = []
    for row in f:
        for y in x.split(','):
            l += [z.strip() for z in y.split('-')]
Python解决方案

data = """3074
88, 3074
1935, 3478-3480
3074, 3478-3479
27015-27030, 27036-27037
4380, 27000-27031, 27036"""
delimiters = "\n\r\t,"
for d in delimiters:
    data = data.replace(d, ' ')

lines = data.split(' ')
numbers = []
i = 0
for line in lines:
    if line == '':
        continue
    elif '-' in line:
        t = line.split('-')
        numbers += range(int(t[0]), int(t[1]) + 1)
    else:
        numbers.append(int(line))
输出: [3074, 88, 3074, 1935, 3478, 3479, 3480, 3074, 3478, 3479, 27015, 27016, 27017, 27018, 27019, 27020, 27021, 27022, 27023, 27024, 27025, 27026, 27027, 27028, 27029, 27030, 27036, 27037, 4380, 27000, 27001, 27002, 27003, 27004, 27005, 27006, 27007, 27008, 27009, 27010, 27011, 27012, 27013, 27014, 27015, 27016, 27017, 27018, 27019, 27020, 27021, 27022, 27023, 27024, 27025, 27026, 27027, 27028, 27029, 27030, 27031, 27036]


Excel VBA解决方案如下,使用Chip Pearson奇妙的SplitEx函数

Sub remove_spclChar()
Dim rng As Range, l As Variant, i As Long
Dim ctr As Long: ctr = 1
For Each rng In Range("A1:A6")
l = SplitEx(rng.Value, True, ",", "-")
For i = LBound(l) To UBound(l)
Range("B" & ctr).Value = l(i)
ctr = ctr + 1
 Next i
Next
 End Sub
 Function SplitEx(ByVal InString As String, IgnoreDoubleDelmiters As _
 Boolean, _
    ParamArray Delims() As Variant) As String()
 Dim Arr() As String
 Dim Ndx As Long
 Dim N As Long

If Len(InString) = 0 Then
    SplitEx = Arr
    Exit Function
End If
If IgnoreDoubleDelmiters = True Then
    For Ndx = LBound(Delims) To UBound(Delims)
        N = InStr(1, InString, Delims(Ndx) & Delims(Ndx), vbTextCompare)
        Do Until N = 0
            InString = Replace(InString, Delims(Ndx) & Delims(Ndx), _
            Delims(Ndx))
            N = InStr(1, InString, Delims(Ndx) & Delims(Ndx), _
            vbTextCompare)
        Loop
    Next Ndx
End If


ReDim Arr(1 To Len(InString))
For Ndx = LBound(Delims) To UBound(Delims)
    InString = Replace(InString, Delims(Ndx), Chr(1))
Next Ndx
Arr = Split(InString, Chr(1))
SplitEx = Arr
End Function

下面是另一个使用嵌套循环的VBA解决方案

Option Explicit
Sub convertToList()
    Dim r As Range, c As Range, v, w, x, vres
    Dim i As Long
    Dim col As Collection

'Data in column A
With ActiveSheet
    Set r = .Range(.Cells(1, 1), .Cells(.Rows.Count, 1).End(xlUp))
End With

Set col = New Collection
For Each c In r
    v = Split(c, ",")
    For Each w In v
        x = Split(w, "-")
            For i = x(LBound(x)) To x(UBound(x))
                col.Add i
            Next i
    Next w
Next c

ReDim vres(1 To col.Count, 1 To 1)
i = 0
For Each v In col
    i = i + 1
    vres(i, 1) = v
Next v

With r.Offset(0, 1).Resize(rowsize:=UBound(vres))
    .EntireColumn.Clear
    .Value = vres
    .EntireColumn.AutoFit
End With

End Sub

嗨,如果我想做同样的事情,除了字母数字值怎么办

例如,我想将第一列中的值展开为第二列

  • 2.
    但不是预期的输出。您的示例不是列表。你是说它是一个长字符串,还是每行一个字符串?格式正确嘿,Obaid,你能把文本组织成你的答案,这样就不需要外部链接了吗?
    A411-A414
    A4150-A4153
    A4159
    A4181
    A4189
    A419
    A427
    A5601-A5602
    A5611
    D65
    D700-D704
    D708-D709
    D7289
    
    A411
    A412
    A413
    A414
    A4150
    A4151
    A4152
    A4153
    A4159
    A4181
    A4189
    A419
    A427
    A5601
    A5602
    A5611
    D65
    D700
    D701
    D702
    D703
    D704
    D708
    D709
    D7289