是多级列表理解中必需的中间列表

时间:2017-08-10 15:04:22

标签: python python-3.x python-3.6

这是一个具体的例子:

my_dict={k:int(encoded_value) 
         for (k,encoded_value) in 
             [encoded_key_value.split('=') for encoded_key_value in 
              many_encoded_key_values.split(',')]}

问题是关于内部列表[],可以避免,例如:

# This will not parse
my_dict={k:int(encoded_value) 
         for (k,encoded_value) in 
             encoded_key_value.split('=') for encoded_key_value in 
             many_encoded_key_values.split(',')}

...,这是无效的语法:

NameError: name 'encoded_key_value' is not defined

示例数据:aa=1,bb=2,cc=3,dd=4,ee=-5

4 个答案:

答案 0 :(得分:5)

如前所述,生成器表达式将增强您的方法,避免创建内部列表。但是使用re.findall()函数获得所需结果的方法较短:

result = {k:int(v) for k,v in re.findall(r'(\w+)=([^,]+)', many_encoded_key_values)}
print(result)

输出:

{'dd': 4, 'aa': 1, 'bb': 2, 'ee': -5, 'cc': 3}

替代方法是使用re.finditer()函数返回'callable_iterator'实例:

result = {m.group(1):int(m.group(2)) for m in re.finditer(r'(\w+)=([^,]+)', many_encoded_key_values)}

答案 1 :(得分:3)

您可以通过使用中间生成器表达式来避免创建中间列表:

.split

语法方面,这几乎是一样的;不是首先生成中间列表然后使用元素,而是动态消耗元素。

使这个过于冗长,您可以使用数据管道'由发电机组成:

split

(遗憾的是func receiptValidation() { // appStoreReceiptURL still says sandboxReceipt if let appStoreReceiptURL = Bundle.main.appStoreReceiptURL, FileManager.default.fileExists(atPath: appStoreReceiptURL.path) { do { let receiptData = try Data(contentsOf: appStoreReceiptURL, options: .alwaysMapped) let receiptString = receiptData.base64EncodedString(options: []) let dict = ["receipt-data" : receiptString, "password" : iTunesMasterAppSecret] as [String : Any] do { let jsonData = try JSONSerialization.data(withJSONObject: dict, options: .prettyPrinted) var receiptUrl:String if (liveMode) { receiptUrl = "https://buy.itunes.apple.com/verifyReceipt" } else { receiptUrl = "https://sandbox.itunes.apple.com/verifyReceipt" } // appStoreReceiptURL still says sandboxReceipt if let sandboxURL = Foundation.URL(string:receiptUrl) { var request = URLRequest(url: sandboxURL) request.httpMethod = "POST" request.httpBody = jsonData let session = URLSession(configuration: URLSessionConfiguration.default) let task = session.dataTask(with: request) { if let receivedData = data, let httpResponse = response as? HTTPURLResponse, error == nil, httpResponse.statusCode == 200 { do { if let jsonResponse = try JSONSerialization.jsonObject(with: receivedData, options: JSONSerialization.ReadingOptions.mutableContainers) as? Dictionary<String, AnyObject> 没有返回生成器,因此考虑节省空间这没什么用处......对于处理大文件这样的事情可能会派上用场。)

找到this answer,其21007 -- This receipt is from the test environment, but it was sent to the production environment for verification. Send it to the test environment instead. 作为迭代器。以防万一......

答案 2 :(得分:1)

FWIW,这是一种功能性方法:

def convert(s):
    k, v = s.split('=')
    return k, int(v)

d = dict(map(convert, data.split(',')))
print(d)

<强>输出

{'aa': '1', 'bb': '2', 'cc': '3', 'dd': '4', 'ee': '-5'}

答案 3 :(得分:0)

一个简单而紧凑的变体,与您原来的尝试非常接近:

d = {v.strip(): int(i) for s in data.split(',') for v, i in (s.split('='),)}

唯一的额外&#39;技巧&#39;是将s.split('=')包装在元组内(用括号括起来(s.split('='),)),以便在同一split次迭代中获取for的两个元素。其余的很简单。