我是Python的新手,无法找到解决问题的方法。我想根据列表项的开头将列表拆分为两个列表。我的列表看起来像这样,每行代表一个项目(是的,这不是正确的列表符号,但为了更好的概述,我会留下这样的):
***
**
.param
+foo = bar
+foofoo = barbar
+foofoofoo = barbarbar
.model
+spam = eggs
+spamspam = eggseggs
+spamspamspam = eggseggseggs
所以我想要一个包含以' +'开头的所有行的列表.param和.model之间的另一个列表,其中包含以' +'开头的所有行模特直到结束。
我查看了enumerate()和split(),但由于我有一个列表而不是字符串,并且我没有尝试匹配列表中的所有项目,所以我不确定如何实现它们。 我有这个:
paramList = []
for line in newContent:
while line.startswith('+'):
paramList.append(line)
if line.startswith('.'):
break
这只是我尝试创建第一个列表。问题是,代码也读取了第二个' +' s,因为break只退出while循环,而不是for循环。 我希望你能理解我的问题,并提前感谢任何指示!
答案 0 :(得分:2)
data = {}
for line in newContent:
if line.startswith('.'):
cur_dict = {}
data[line[1:]] = cur_dict
elif line.startswith('+'):
key, value = line[1:].split(' = ', 1)
cur_dict[key] = value
这会产生一个dicts的字典:
{'model': {'spam': 'eggs',
'spamspam': 'eggseggs',
'spamspamspam': 'eggseggseggs'},
'param': {'foo': 'bar',
'foofoo': 'barbar',
'foofoofoo': 'barbarbar'}}
答案 1 :(得分:1)
我是Python的新手
糟糕。不要再烦我的回答了。
我想要一个包含所有以'+'开头的行的列表 .param和.model以及包含所有行开头的另一个列表 在模型之后使用'+'直到结束。
import itertools as it
import pprint
data = [
'***',
'**',
'.param',
'+foo = bar',
'+foofoo = barbar',
'+foofoofoo = barbarbar',
'.model',
'+spam = eggs',
'+spamspam = eggseggs',
'+spamspamspam = eggseggseggs',
]
results = [
list(group) for key, group in it.groupby(data, lambda s: s.startswith('+'))
if key
]
pprint.pprint(results)
print '-' * 20
print results[0]
print '-' * 20
pprint.pprint(results[1])
--output:--
[['+foo = bar', '+foofoo = barbar', '+foofoofoo = barbarbar'],
['+spam = eggs', '+spamspam = eggseggs', '+spamspamspam = eggseggseggs']]
--------------------
['+foo = bar', '+foofoo = barbar', '+foofoofoo = barbarbar']
--------------------
['+spam = eggs', '+spamspam = eggseggs', '+spamspamspam = eggseggseggs']
这件事:
it.groupby(data, lambda x: x.startswith('+')
...告诉python根据字符串的第一个字符创建字符串组。如果第一个字符是'+',则字符串将被置于True组中。如果第一个字符不是'+',则字符串将被置于False组中。但是,有两个以上的组,因为连续的False字符串将形成一个组,连续的True字符串将形成一个组。
根据您的数据,前三个字符串:
***
**
.param
将创建一个False组。然后,接下来的字符串:
+foo = bar
+foofoo = barbar
+foofoofoo = barbarbar
将创建一个True组。然后是下一个字符串:
'.model'
将创建另一个False组。然后是下一个字符串:
'+spam = eggs'
'+spamspam = eggseggs'
'+spamspamspam = eggseggseggs'
将创建另一个True组。结果将是:
{
False: [strs here],
True: [strs here],
False: [strs here],
True: [strs here]
}
然后,只需选择每个True组:if key
,然后将相应的组转换为列表:list(group)
。
对评论的回应:
python究竟在哪里通过数据,就像它知道的那样 它正在迭代的数据?
groupby()的工作方式如下面的do_stuff():
def do_stuff(items, func):
for item in items:
print func(item)
#Create the arguments for do_stuff():
data = [1, 2, 3]
def my_func(x):
return x + 100
#Call do_stuff() with the proper argument types:
do_stuff(data, my_func) #Just like when calling groupby(), you provide some data
#and a function that you want applied to each item in data
--output:--
101
102
103
也可以这样写:
do_stuff(data, lambda x: x + 100)
lambda
创建一个匿名函数,这对于您不需要通过名称引用的简单函数很方便。
此列表理解:
[
list(group)
for key, group in it.groupby(data, lambda s: s.startswith('+'))
if key
]
等同于:
results = []
for key, group in it.groupby(data, lambda s: s.startswith('+') ):
if key:
results.append(list(group))
显式编写for循环更清楚,但列表推导执行得更快。这是一些细节:
[
list(group) #The item you want to be in the results list for the current iteration of the loop here:
for key, group in it.groupby(data, lambda s: s.startswith('+')) #A for loop
if key #Only include the item for the current loop iteration in the results list if key is True
]
答案 2 :(得分:1)
你想要的是一个简单的任务,可以使用列表切片和列表理解来完成:
data = ['**','***','.param','+foo = bar','+foofoo = barbar','+foofoofoo = barbarbar',
'.model','+spam = eggs','+spamspam = eggseggs','+spamspamspam = eggseggseggs']
# First get the interesting positions.
param_tag_pos = data.index('.param')
model_tag_pos = data.index('.model')
# Get all elements between tags.
params = [param for param in data[param_tag_pos + 1: model_tag_pos] if param.startswith('+')]
models = [model for model in data[model_tag_pos + 1: -1] if model.startswith('+')]
print(params)
print(models)
输出
>>> ['+foo = bar', '+foofoo = barbar', '+foofoofoo = barbarbar']
>>> ['+spam = eggs', '+spamspam = eggseggs']
回答评论:
假设您有一个包含0到5之间的数字的列表。
l = [0, 1, 2, 3, 4, 5]
然后使用列表slices,您可以选择l
的一个子集:
another = l[2:5] # another is [2, 3, 4]
我们在这里做的是:
data[param_tag_pos + 1: model_tag_pos]
对于你的上一个问题: ... python如何知道param是它应该迭代的数据中的行以及paramdo的第一个paramin param到底是什么?
Python不知道,你必须告诉他。首先param
是我在这里使用的变量名称,它是x
,list_items
,无论你想要什么。
我会将代码行翻译成普通英语:
# Pythonian
params = [param for param in data[param_tag_pos + 1: model_tag_pos] if param.startswith('+')]
# English
params is a list of "things", for each "thing" we can see in the list `data`
from position `param_tag_pos + 1` to position `model_tag_pos`, just if that "thing" starts with the character '+'.
答案 3 :(得分:0)
我建议一步一步做。
1)分别从阵列中抓取每个单词。
2)抓住单词的第一个字母。
3)看看那是'+'还是'。'
示例代码:
import re
class Dark():
def __init__(self):
# Array
x = ['+Hello', '.World', '+Hobbits', '+Dwarves', '.Orcs']
xPlus = []
xDot = []
# Values
i = 0
# Look through every word in the array one by one.
while (i != len(x)):
# Grab every word (s), and convert to string (y).
s = x[i:i+1]
y = '\n'.join(s)
# Print word
print(y)
# Grab the first letter.
letter = y[:1]
if (letter == '+'):
xPlus.append(y)
elif (letter == '.'):
xDot.append(y)
else:
pass
# Add +1
i = i + 1
# Print lists
print(xPlus)
print(xDot)
#Run class
Dark()