如何从带有重复值的逗号分隔字符串创建具有唯一索引的Python列表?

0 投票
4 回答
1072 浏览
提问于 2025-04-18 07:58

我正在尝试用 Python 中的 split() 方法把一个用逗号分隔的字符串转换成一个列表。我发现这样做后,列表里有很多重复的索引,这似乎是因为有些值是相同的。我希望每个元素都有自己独特的顺序索引,这样我就可以通过索引来按位置访问它们,我该怎么做呢?以下是相关的代码:

haproxy_socket_data ='''
pxname,svname,qcur,qmax,scur,smax,slim,stot,bin,bout,dreq,dresp,ereq,econ,eresp,wretr,wredis,status,weight,act,bck,chkfail,chkdown,lastchg,downtime,qlimit,pid,iid,sid,throttle,lbtot,tracked,type,rate,rate_lim,rate_max,check_status,check_code,check_duration,hrsp_1xx,hrsp_2xx,hrsp_3xx,hrsp_4xx,hrsp_5xx,hrsp_other,hanafail,req_rate,req_rate_max,req_tot,cli_abrt,srv_abrt,
fe,FRONTEND,,,0,1,2000,45,0,8415,0,0,45,,,,,OPEN,,,,,,,,,1,1,0,,,,0,0,0,1,,,,0,0,0,45,0,0,,0,1,45,,,
bend,host1,0,0,0,0,,0,0,0,,0,,0,0,0,0,UP,1,1,0,0,0,113,0,,1,2,1,,0,,2,0,,0,L4OK,,0,0,0,0,0,0,0,0,,,,0,0,
'''
haproxy_socket_data = haproxy_socket_data.splitlines()

for line in haproxy_socket_data:
    stats = line.split(',')
    print line
    print stats
    for i in stats:
        print i
        print "index: %s" % stats.index(i)

这是这段代码的输出结果: https://gist.github.com/wjimenez5271/74df2b16b540a7d9de0c

我找到了这些关于如何将数据放入列表的例子,但没有一个解决我这个情况,也就是有些值是相同的:

如何在 Python 中分割这个用逗号分隔的字符串?

如何将用逗号分隔的字符串转换为 Python 中的列表?

4 个回答

1

看起来你有重复的索引,其实是因为在Python中,list.index()这个方法只会返回那个值第一次出现的位置。你可以试着用一个for循环,逐个索引这些值,而不是用那种自动迭代的for in循环。

1

如果你想保留索引,可以使用一个带有 enumeratefor 循环,或者用 range()

haproxy_socket_data = """
pxname,svname,qcur,qmax,scur,smax,slim,stot,bin,bout,dreq,dresp,ereq,econ,eresp,wretr,wredis,status,weight,act,bck,chkfail,chkdown,lastchg,downtime,qlimit,pid,iid,sid,throttle,lbtot,tracked,type,rate,rate_lim,rate_max,check_status,check_code,check_duration,hrsp_1xx,hrsp_2xx,hrsp_3xx,hrsp_4xx,hrsp_5xx,hrsp_other,hanafail,req_rate,req_rate_max,req_tot,cli_abrt,srv_abrt,
fe,FRONTEND,,,0,1,2000,45,0,8415,0,0,45,,,,,OPEN,,,,,,,,,1,1,0,,,,0,0,0,1,,,,0,0,0,45,0,0,,0,1,45,,,
bend,
"""
haproxy_socket_data = haproxy_socket_data.splitlines()
for line in haproxy_socket_data:
    stats = [item for item in line.split(',') if len(item) >= 1] #Gets rid of items like ['']
    print line
    print stats
    for ind, it in enumerate(stats):
        print it
        print "index: %d" % ind

或者,使用 range(len())

haproxy_socket_data ="""
    pxname,svname,qcur,qmax,scur,smax,slim,stot,bin,bout,dreq,dresp,ereq,econ,eresp,wretr,wredis,status,weight,act,bck,chkfail,chkdown,lastchg,downtime,qlimit,pid,iid,sid,throttle,lbtot,tracked,type,rate,rate_lim,rate_max,check_status,check_code,check_duration,hrsp_1xx,hrsp_2xx,hrsp_3xx,hrsp_4xx,hrsp_5xx,hrsp_other,hanafail,req_rate,req_rate_max,req_tot,cli_abrt,srv_abrt,
    fe,FRONTEND,,,0,1,2000,45,0,8415,0,0,45,,,,,OPEN,,,,,,,,,1,1,0,,,,0,0,0,1,,,,0,0,0,45,0,0,,0,1,45,,,
    bend,
    """
haproxy_socket_data = haproxy_socket_data.splitlines()
for line in haproxy_socket_data:
    stats = [item for item in line.split(',') if len(item) >= 1] #Gets rid of items like ['']
    print line
    print stats
    for i in range(len(stats):
        print stats[i]
        print "index: %d" % i

list.index() 会返回这个项目的第一次出现的位置:

>>> item = [1, 2, 5, 7, 3, 3, 8, 9, 5]
>>> item.index(5)
2
>>> item[2]
5
>>> item[8]
5
>>> 

使用 enumerate()

>>> for ind, it in enumerate(item):
...     if it == 5:
...             print ind
... 
2
8
>>> 
1

如果数据值中有逗号,那么直接用 split(",") 来分割就不对了。

可以看看 csv 模块。这个模块可以自动判断(也就是“嗅探”)正确的分割和引号参数。它还可以把每一行数据读到一个字典里,这样你就可以通过名字来引用数据,而不需要再数列数了!

举个例子。注意反斜杠,这样嗅探器才能从数据的第一行读取标题:

haproxy_socket_data ='''\
pxname,svname,qcur,qmax,scur,smax,slim,stot,bin,bout,dreq,dresp,ereq,econ,eresp,wretr,wredis,status,weight,act,bck,chkfail,chkdown,lastchg,downtime,qlimit,pid,iid,sid,throttle,lbtot,tracked,type,rate,rate_lim,rate_max,check_status,check_code,check_duration,hrsp_1xx,hrsp_2xx,hrsp_3xx,hrsp_4xx,hrsp_5xx,hrsp_other,hanafail,req_rate,req_rate_max,req_tot,cli_abrt,srv_abrt,
fe,FRONTEND,,,0,1,2000,45,0,8415,0,0,45,,,,,OPEN,,,,,,,,,1,1,0,,,,0,0,0,1,,,,0,0,0,45,0,0,,0,1,45,,,
bend,host1,0,0,0,0,,0,0,0,,0,,0,0,0,0,UP,1,1,0,0,0,113,0,,1,2,1,,0,,2,0,,0,L4OK,,0,0,0,0,0,0,0,0,,,,0,0,
'''

import csv, StringIO

dialect = csv.Sniffer().sniff(haproxy_socket_data)

reader = csv.reader( 
    StringIO.StringIO(haproxy_socket_data), dialect=dialect,
    )
for row in reader:
    print row

print

dictr = csv.DictReader( 
    StringIO.StringIO(haproxy_socket_data),
    dialect=dialect,
    )
for drow in dictr:
    print 'svname',drow['svname']

输出结果:

['pxname', 'svname', 'qcur', 'qmax', 'scur', 'smax', 'slim', 'stot', 'bin', 'bout', 'dreq', 'dresp', 'ereq', 'econ', 'eresp', 'wretr', 'wredis', 'status', 'weight', 'act', 'bck', 'chkfail', 'chkdown', 'lastchg', 'downtime', 'qlimit', 'pid', 'iid', 'sid', 'throttle', 'lbtot', 'tracked', 'type', 'rate', 'rate_lim', 'rate_max', 'check_status', 'check_code', 'check_duration', 'hrsp_1xx', 'hrsp_2xx', 'hrsp_3xx', 'hrsp_4xx', 'hrsp_5xx', 'hrsp_other', 'hanafail', 'req_rate', 'req_rate_max', 'req_tot', 'cli_abrt', 'srv_abrt', ''] ['fe', 'FRONTEND', '', '', '0', '1', '2000', '45', '0', '8415', '0', '0', '45', '', '', '', '', 'OPEN', '', '', '', '', '', '', '', '', '1', '1', '0', '', '', '', '0', '0', '0', '1', '', '', '', '0', '0', '0', '45', '0', '0', '', '0', '1', '45', '', '', ''] ['bend', 'host1', '0', '0', '0', '0', '', '0', '0', '0', '', '0', '', '0', '0', '0', '0', 'UP', '1', '1', '0', '0', '0', '113', '0', '', '1', '2', '1', '', '0', '', '2', '0', '', '0', 'L4OK', '', '0', '0', '0', '0', '0', '0', '0', '0', '', '', '', '0', '0', '']

svname FRONTEND svname host1

3

你对 index() 的功能有些误解。Python 的文档上是这么说的:

s.index(x[, i[, j]])

s 中,x 第一次出现的位置(从索引 i 开始,到索引 j 之前)

所以,每次你在代码中调用 stats.index(i) 时,它会返回 istats 中第一次出现的位置。

如果你想在遍历列表时跟踪每个元素的索引,你应该使用 enumerate()

for index, item in enumerate(stats):
    print item
    print "index: %s" % index

撰写回答