2016-02-25 15 views
9

Tôi có một chuỗi có các từ được phân cách bằng dấu cách. Tôi bật chuỗi này vào danh sách:Cách chuyển chuỗi thành dict

out = str.split() 

Và đếm bao nhiêu giá trị được tạo ra:

print len(out) # Says 192 

Sau đó, tôi cố gắng để xóa tất cả mọi thứ từ danh sách:

for x in out: 
    out.remove(x) 

Và sau đó đếm lại :

print len(out) # Says 96 

C một ai đó giải thích xin vui lòng tại sao nó nói 96 thay vì 0 ???

INFO THÊM

chuỗi của tôi trông như thế này: chó mèo #one #two #three chim Không có bản sao trong chuỗi, tất cả các từ là duy nhất.

Vì vậy, những gì tôi đang làm là:

for x in out: 
    if '#' in x: 
      ind = out.index(x) # Get current index 
      nextValue = out[ind+1] # Get next value 
      myDictionary[x] = nextValue 
      out.remove(nextValue) 
      out.remove(x) 

Vấn đề là tôi không thể di chuyển tất cả các giá trị cặp vào một cuốn từ điển kể từ khi tôi chỉ lặp thông qua 96 hạng mục.

Cảm ơn tất cả mọi người!

+1

"Sau đó, tôi cố gắng xóa mọi thứ khỏi danh sách" - hãy tìm hiểu kỹ hơn tại đây. Tại sao bạn muốn làm nó? –

+0

Vì tôi đang di chuyển các giá trị từ danh sách sang một từ điển theo cặp, như giá trị đầu tiên trong cặp là khóa và giá trị thứ hai là giá trị. Điều này là từ điển của tôi là không đầy đủ do tôi không thể lặp qua danh sách đầy đủ - nó nói chỉ có 96 chỉ mục. – user4447655

+0

Nếu bạn có thể đăng mã bằng chuỗi và dict bạn đang sử dụng, chúng tôi sẽ cung cấp giải pháp dễ dàng hơn. Vấn đề có thể ở đâu đó khác với những gì bạn đã cho chúng tôi cho đến nay. – MKreegs

Trả lời

9

Tôi nghĩ rằng bạn thực sự muốn một cái gì đó như thế này:

s = '#one cat #two dogs #three birds' 
out = s.split() 
entries = dict([(x, y) for x, y in zip(out[::2], out[1::2])]) 

được mã này làm gì vậy? Hãy chia nhỏ nó đi. Trước tiên, chúng tôi chia s bằng khoảng trắng thành out như bạn đã có.

Tiếp theo, chúng tôi lặp qua các cặp trong out, gọi chúng là "x, y". Các cặp đó trở thành list của bộ/cặp. dict() chấp nhận danh sách có kích thước hai bộ và xử lý chúng là key, val.

Dưới đây là những gì tôi nhận được khi tôi đã thử nó:

$ cat tryme.py 

s = '#one cat #two dogs #three birds' 
out = s.split() 
entries = dict([(x, y) for x, y in zip(out[::2], out[1::2])]) 

from pprint import pprint 
pprint(entries) 

$ python tryme.py 
{'#one': 'cat', '#three': 'birds', '#two': 'dogs'} 
+0

Yep, hoạt động! Cảm ơn bạn rất nhiều. Có cách nào tôi cũng có thể bao gồm một điều kiện vào quá trình này? Bởi vì tôi cần phải sửa đổi một số giá trị trước khi chuyển chúng vào một từ điển. Tôi cần phải thoát khỏi một dấu băm, đã làm điều đó thông qua mục = dict ([(x [1:], y) cho x, y trong zip (ra [:: 2], ra [1 :: 2])]) nhưng trong một số trường hợp, tôi sẽ cần phải sửa đổi các ký tự nhất định, ví dụ, nếu từ đó chứa 'từ khóa' tôi cần phải thay thế nó bằng một từ khác. – user4447655

+0

Viết lại "danh sách hiểu" như một vòng lặp 'for' truyền thống. Dòng đầu tiên giống như "' cho khóa, val trong zip (out [:: 2], out [1 :: 2]): 'và sau đó bạn có thể làm bất cứ điều gì bạn muốn' key' hoặc 'val'. để dict của bạn như vậy: 'mục [key] = val' Đừng quên để tạo ra các dict lúc đầu,' mục = {} ', ví dụ như –

+0

Cảm ơn bạn! Thực sự đánh giá cao sự giúp đỡ của bạn! – user4447655

3

Bạn đang không được cụ thể. Tại sao bạn đang cố xóa mọi thứ trong danh sách ngoài? Bất kỳ nếu tất cả những gì bạn cần làm là xóa danh sách ngoài, tại sao không chỉ làm như vậy:

out = [] 
0

Vấn đề là bạn đang sử dụng xóa (x) trong khi lặp lại. biến 'out' là tham chiếu cả trong hàm remove và for-loop.

Chỉ cần sử dụng

for i in range(len(out)): 
    out.remove(out[i]); 
1

Nếu bạn chỉ cần xóa trong danh sách,

sử dụng out = [] hoặc out.clear()

Dù sao, mà bạn nói là vì remove chức năng của danh sách ảnh hưởng đến danh sách .

out = ['a', 'b', 'c', 'd', 'e', 'f'] 
for x in out: 
    out.remove(x) 
    print(x) 

thì kết quả được hiển thị dưới đây:

một c e

Đó là chính xác một nửa danh sách đầy đủ. Vì vậy, trong trường hợp của bạn, bạn có 96 (một nửa trong số 192) từ 192.

12

Đối với những gì thực sự xảy ra trong cho loop:

TừPython for statement documentation:

Các danh sách biểu thức được đánh giá sau khi; cần tạo đối tượng có thể lặp lại. Trình lặp được tạo cho kết quả của expression_list. Sau đó, suite được thực hiện một lần cho mỗi mục được cung cấp bởi máy phát lặp , theo thứ tự chỉ số tăng dần. Mỗi mục lần lượt là được gán cho mục tiêu danh sách sử dụng các quy tắc tiêu chuẩn cho bài tập, và sau đó bộ được thực thi. Khi các mặt hàng đang cạn kiệt (đó là ngay lập tức khi chuỗi là trống), bộ ứng dụng trong mệnh đề else, nếu có, được thực thi, và loopchấm dứt.

Tôi nghĩ điều đó được thể hiện tốt nhất với sự trợ giúp của hình minh họa minh họa.

Bây giờ, giả sử bạn có một iterable object (như list) như thế này:

out = [a, b, c, d, e, f] 

gì xảy ra khi bạn làm for x in out là nó tạo nội indexer mà đi như thế này (tôi minh họa cho nó với biểu tượng ^):

[a, b, c, d, e, f] 
^ <-- here is the indexer 

gì thường xảy ra đó là: khi bạn kết thúc một chu kỳ của vòng lặp của bạn, di chuyển indexer chuyển tiếp như thế này:

[a, b, c, d, e, f] #cycle 1 
^ <-- here is the indexer 

[a, b, c, d, e, f] #cycle 2 
    ^<-- here is the indexer 

[a, b, c, d, e, f] #cycle 3 
    ^<-- here is the indexer 

[a, b, c, d, e, f] #cycle 4 
     ^<-- here is the indexer 

[a, b, c, d, e, f] #cycle 5 
      ^<-- here is the indexer 

[a, b, c, d, e, f] #cycle 6 
       ^<-- here is the indexer 

#finish, no element is found anymore! 

Như bạn có thể thấy, indexer tiếp tục di chuyển về phía trước cho đến cuối danh sách của bạn, bất kể những gì đã xảy ra với danh sách!

Như vậy khi bạn làm remove, đây là những gì đã xảy ra trong nội bộ:

[a, b, c, d, e, f] #cycle 1 
^ <-- here is the indexer 

[b, c, d, e, f] #cycle 1 - a is removed! 
^ <-- here is the indexer 

[b, c, d, e, f] #cycle 2 
    ^<-- here is the indexer 

[c, d, e, f] #cycle 2 - c is removed 
    ^<-- here is the indexer 

[c, d, e, f] #cycle 3 
    ^<-- here is the indexer 

[c, d, f] #cycle 3 - e is removed 
    ^<-- here is the indexer 

#the for loop ends 

Chú ý rằng chỉ có 3 chu kỳ có thay vì 6 chu kỳ (!!) (là số lượng các phần tử trong danh sách gốc). Và đó là lý do bạn rời đi với một nửalen trong số len ban đầu của bạn, vì đó là số chu kỳ cần để hoàn thành vòng lặp khi bạn xóa một phần tử khỏi nó cho mỗi chu kỳ.


Nếu bạn muốn xóa danh sách, chỉ cần làm:

if (out != []): 
    out.clear() 

Hoặc cách khác, để loại bỏ các phần tử từng người một, bạn cần phải làm điều đó cách khác xung quanh - từ kết thúc vào đầu. Sử dụng reversed:

for x in reversed(out): 
    out.remove(x) 

Bây giờ, tại sao công việc reversed? Nếu người lập chỉ mục tiếp tục di chuyển về phía trước, thì không phải reversed cũng sẽ không hoạt động do số lượng phần tử được giảm một lần cho mỗi chu kỳ không?

Không, nó không giống như vậy,

reversed phương pháp thay đổi cách để indexer nội công trình! Điều gì đã xảy ra khi bạn sử dụng phương pháp reversedđể làm cho chỉ mục nội bộ di chuyển lùi (từ cuối) thay vì về phía trước.

Để minh họa, đây là những gì thường xảy ra:

[a, b, c, d, e, f] #cycle 1 
       ^<-- here is the indexer 

[a, b, c, d, e, f] #cycle 2 
      ^<-- here is the indexer 

[a, b, c, d, e, f] #cycle 3 
     ^<-- here is the indexer 

[a, b, c, d, e, f] #cycle 4 
    ^<-- here is the indexer 

[a, b, c, d, e, f] #cycle 5 
    ^<-- here is the indexer 

[a, b, c, d, e, f] #cycle 6 
^ <-- here is the indexer 

#finish, no element is found anymore! 

Và như vậy, khi bạn làm một việc loại bỏ mỗi chu kỳ, nó không ảnh hưởng đến cách indexer hoạt động:

[a, b, c, d, e, f] #cycle 1 
       ^<-- here is the indexer 

[a, b, c, d, e] #cycle 1 - f is removed 
       ^<-- here is the indexer 

[a, b, c, d, e] #cycle 2 
      ^<-- here is the indexer 

[a, b, c, d] #cycle 2 - e is removed 
      ^<-- here is the indexer 

[a, b, c, d] #cycle 3 
     ^<-- here is the indexer 

[a, b, c] #cycle 3 - d is removed 
     ^<-- here is the indexer 

[a, b, c] #cycle 4 
    ^<-- here is the indexer 

[a, b] #cycle 4 - c is removed 
    ^<-- here is the indexer 

[a, b] #cycle 5 
    ^<-- here is the indexer 

[a] #cycle 5 - b is removed 
    ^<-- here is the indexer 

[a] #cycle 6 
^ <-- here is the indexer 

[] #cycle 6 - a is removed 
^ <-- here is the indexer 

Hope hình minh họa giúp bạn hiểu những gì đang diễn ra trong nội bộ ...

+1

Đây là một trong những giải thích tốt nhất về sửa đổi trong khi lặp lại mà tôi từng thấy. Tôi ước tôi có thể upvote điều này nhiều hơn một lần! –

+1

Bạn đã đưa ra giải thích rõ ràng cho câu trả lời của tôi! Cảm ơn bạn rất nhiều! – user4447655

+1

Vừa mới đăng một ví dụ nhỏ, cảm ơn bạn đã giải quyết câu hỏi thực tế! – pyInTheSky

2

Sự cố bạn đang gặp phải là kết quả của việc sửa đổi li st trong khi lặp qua nó. Khi một mục bị xóa, mọi thứ sau khi nó được di chuyển về phía trước bởi một chỉ mục, nhưng trình vòng lặp không tính đến thay đổi và tiếp tục bằng cách tăng chỉ số mà nó được truy cập lần cuối. Trình vòng lặp như vậy sẽ bỏ qua mọi phần tử thứ hai trong danh sách, đó là lý do tại sao bạn còn lại với một nửa số phần tử.

Giải pháp trực tiếp đơn giản nhất để vấn đề của bạn là để lặp qua một bản sao của out, sử dụng ký hiệu lát:

for x in out[:]: 
    # ... 
    out.remove(x) 

Tuy nhiên, có một câu hỏi sâu hơn ở đây: tại sao bạn cần phải loại bỏ các mục từ danh sách ở tất cả? Với thuật toán của bạn, bạn được đảm bảo để kết thúc với một danh sách trống, đó là không sử dụng cho bạn. Nó sẽ đơn giản hơn và hiệu quả hơn để chỉ lặp qua danh sách mà không xóa các mục.

Khi bạn đã hoàn thành danh sách (sau khối lặp), bạn có thể xóa nó một cách rõ ràng (sử dụng từ khóa del) hoặc đơn giản là để hệ thống thu gom rác của Python xử lý.

Vẫn còn một vấn đề nữa: bạn đang kết hợp lặp lại trực tiếp trên danh sách có tham chiếu dựa trên chỉ mục. Việc sử dụng for x in out thường sẽ bị hạn chế trong các tình huống mà bạn muốn truy cập từng phần tử độc lập với các phần tử khác. Nếu bạn muốn làm việc với các chỉ mục, hãy sử dụng for i in range(len(out)) và truy cập các yếu tố với out[i].

Hơn nữa, bạn có thể sử dụng một sự hiểu biết điển để hoàn thành toàn bộ nhiệm vụ của bạn trong một biểu thức pythonic một dòng:

my_dictionary = {out[i]: out[i + 1] for i in range(len(out)) if "#" in out[i]} 

Một thay thế pythonic sẽ tận dụng thực tế là mỗi số chẵn phần tử là khóa và mỗi phần tử được đánh số lẻ là một giá trị (bạn phải giả định rằng kết quả danh sách của str.split() liên tục tuân theo mẫu này) và sử dụng zip trên danh sách phụ chẵn và lẻ.

my_dictionary = dict(zip(out[::2], out[1::2])) 
2

Tôi tin rằng bạn muốn theo dõi.

>>> a = '#one cat #two dogs #three birds' 
>>> b = { x.strip().split(' ')[0] : x.strip().split(' ')[-1] for x in a.strip().split('#') if len(x) > 0 } 
>>> b 
{'three': 'birds', 'two': 'dogs', 'one': 'cat'} 

Hoặc thậm chí tốt hơn

>>> b = [ y for x in a.strip().split('#') for y in x.strip().split(' ') if len(x) > 0 ] 
>>> c = { x: y for x,y in zip(b[0::2],b[1::2]) } 
>>> c 
{'three': 'birds', 'two': 'dogs', 'one': 'cat'} 
>>> 
1

Vấn đề là bất cứ khi nào bạn xóa một giá trị từ danh sách, mà danh sách cụ thể phục hồi giá trị của nó tự động. Tức là, khi bạn thực hiện out.remove(ind)out.remove(ind+1), giá trị trong các chỉ mục này sẽ bị xóa, nhưng chúng được thay thế bằng giá trị mới là giá trị trước đó của giá trị trước đó.

Vì vậy để tránh điều này, bạn phải thực hiện các mã như sau:

out = [] 
out = '#one cat #two dogs #three birds'.split() 

print "The list is : {0} \n".format(out) 
myDictionary = dict() 

for x in out: 

    if '#' in x: 
     ind = out.index(x) # Get current index 
     nextValue = out[ind+1] # Get next value 
     myDictionary[x] = nextValue 

out = [] # #emptying the list 
print("The dictionary is : {0} \n".format(myDictionary)) 

Vì vậy, sau khi bạn đã thực hiện chuyển giao các giá trị từ danh sách vào từ điển, chúng tôi một cách an toàn có thể rỗng out bởi sử dụng out = []

Các vấn đề liên quan