2009-09-06 76 views
5

Tôi mới sử dụng Python. Dưới đây là những gì tôi đang cố gắng làm:Chuyển đổi chuỗi nhị phân thành danh sách các số nguyên bằng cách sử dụng Python

  1. Cắt chuỗi nhị phân dài thành 3 chữ số dài.
  2. Lưu từng "đoạn" vào danh sách được gọi là hàng.
  3. Chuyển đổi từng đoạn nhị phân thành một số (0-7).
  4. Lưu trữ danh sách số đã chuyển đổi thành danh sách mới được gọi là số.

Dưới đây là những gì tôi có cho đến nay:

def traverse(R): 
     x = 0 
     while x < (len(R) - 3): 
      row = R[x] + R[x+1] + R[x+2] 
      ??? 

Nhờ sự giúp đỡ của bạn! Được đánh giá cao.

+1

và ** cách ** bạn đang cố thực hiện việc này? hoặc chúng ta chỉ cần cung cấp cho bạn c0dez? – SilentGhost

+0

Tôi sẽ đăng những gì tôi có cho đến nay, mặc dù nó có thể là sai cách để làm điều đó. – AME

Trả lời

11

Something như thế này nên làm điều đó:

s = "110101001" 
numbers = [int(s[i:i+3], 2) for i in range(0, len(s), 3)] 
print numbers 

Đầu ra là:

[6, 5, 1] 

Breaking này xuống từng bước một, đầu tiên:

>>> range(0, len(s), 3) 
[0, 3, 6] 

Chức năng range() tạo ra một danh sách các số nguyên từ 0, nhỏ hơn số tối đa len(s), theo bước 3.

>>> [s[i:i+3] for i in range(0, len(s), 3)] 
["110", "101", "001"] 

Đây là một list comprehension rằng đánh giá s[i:i+3] cho mỗi i trong phạm vi trên. Các s[i:i+3] là một slice mà chọn một chuỗi con. Cuối cùng:

>>> [int(s[i:i+3], 2) for i in range(0, len(s), 3)] 
[6, 5, 1] 

Chức năng int(..., 2) chuyển đổi từ nhị phân (số 2, đối số thứ hai) thành số nguyên.

Lưu ý rằng mã trên có thể không xử lý đúng các điều kiện lỗi như chuỗi đầu vào không phải là bội số của 3 ký tự.

+0

Câu trả lời hay. Bảng phân tích đặc biệt hữu ích nếu bạn không hiểu cú pháp của việc hiểu danh sách. –

+0

Cảm ơn! Câu trả lời của bạn được giải thích rất rõ ràng.Tôi có một câu hỏi mặc dù, nếu chuỗi tham chiếu không phải là bội số của ba thì sao? Có cách nào để xử lý điều đó không? – AME

+0

Đẹp nhất, nó phải là ví dụ python điện và syntac :) – IProblemFactory

7

Tôi giả định rằng bằng "chuỗi nhị phân", bạn thực sự ngụ ý một chuỗi bình thường (ví dụ: văn bản) có các mục là '0' hoặc '1'.

Vì vậy, cho điểm 1 và 2,

row = [thestring[i:i+3] for i in xrange(0, len(thestring), 3)] 

dĩ nhiên mục cuối cùng sẽ dài chỉ có 1 hoặc 2 ký tự nếu len(thestring) không chính xác là bội của 3, đó là không thể tránh khỏi ;-).

Đối với điểm 3 và 4, tôi muốn đề nghị xây dựng một từ điển tạm thời phụ trợ và lưu trữ nó:

aux = {} 
for x in range(8): 
    s = format(x, 'b') 
    aux[s] = x 
    aux[('00'+s)[-3:]] = x 

để chỉ 3 và 4 chỉ trở thành:

numbers = [aux[x] for x in row] 

tra cứu dict này nên nhanh hơn nhiều so với việc chuyển đổi từng mục nhập một cách nhanh chóng.

Chỉnh sửa: tôi đã giải thích tại sao tôi tạo hai mục nhập thành aux cho mỗi giá trị x. Vấn đề là s có thể có độ dài từ 1 đến 3 ký tự và cho độ dài ngắn, tôi muốn hai mục - một với s vì nó (vì như tôi đã đề cập mục cuối cùng trong row cũng có thể ngắn hơn 3 ...) và một có đệm bên trái ở độ dài 3 với 0 s.

Tiểu biểu ('00'+s)[-3:] tính "s trái độn với 'của 0 đến chiều dài của 3" bằng cách lấy 3 ký tự cuối cùng (đó là phần [-3:] cắt) của chuỗi thu được bằng cách đặt số không bên trái của s (đó là phần '00'+s). Nếu s đã dài 3 ký tự, toàn bộ biểu thức con sẽ bằng s do đó việc gán cho mục nhập đó là aux là vô dụng nhưng vô hại, vì vậy tôi thấy việc kiểm tra đơn giản hơn (thậm chí trước một số if len(s)<3: cũng không sao; -).

Có các cách tiếp cận khác (ví dụ: định dạng x một lần nữa nếu cần) nhưng đây không phải là điểm then chốt của mã (nó chỉ thực hiện 8 lần để xây dựng bảng tra cứu phụ, sau khi tất cả ;-), vì vậy tôi đã không 't trả nó đủ sự chú ý.

... Tôi cũng không kiểm tra đơn vị, vì vậy nó có lỗi trong một trường hợp góc tối nghĩa. Bạn có thể thấy nó...?

Giả sử row'01' như mục cuối cùng: RẰNG quan trọng, sau khi mã của tôi ấy trên đã xây dựng aux, sẽ không có mặt trong aux (cả 1001 SẼ được, nhưng đó là ít ỏi ủi ;-). Trong đoạn mã trên, tôi sử dụng s, '1' và phiên bản đệm ba chiều, '001', nhưng phiên bản đệm hai chiều trung gian, oops, bị bỏ qua ;-).

Vì vậy, đây là một cách đúng đắn để làm điều đó ...:

aux = {} 
for x in range(8): 
    s = format(x, 'b') 
    aux[s] = x 
    while len(s) < 3: 
    s = '0' + s 
    aux[s] = x 

... không có nghi ngờ đơn giản và rõ ràng hơn, nhưng, thậm chí quan trọng hơn, ĐÚNG ;-).

+0

Đó là loại lừa có nghĩa là bạn kéo bằng chỉ mục chuỗi. Bạn có thể muốn giải thích những gì đang làm như vậy OP không bị cám dỗ để sao chép/dán nó vào mã của mình mà không hiểu nó. –

+0

@Chris, ý tưởng hay, chỉnh sửa để giải thích. –

+1

Nhìn lên trên bầu trời! Nó mã hóa, nó giải thích, nó thậm chí biến những sai lầm thành bài học! Đó là SUPER MARTELLI, ở đây để hút hạn ngạch hàng ngày của tôi về upvotes! –

0

Câu trả lời hay từ Greg và Alex! Danh sách hiểu và cắt là như vậy pythonic! Đối với chuỗi đầu vào ngắn, tôi sẽ không bận tâm đến thủ thuật tìm kiếm từ điển, nhưng nếu chuỗi đầu vào dài hơn, tôi cũng như sử dụng gen-exps thay vì danh sách-comps, ví dụ:

row = list (theString [i: i + 3] for i in xrange (0, len (theString), 3))

số = danh sách (aux [x] cho x trong hàng)

từ gen-exp hoạt động tốt hơn.

+0

Thực tế danh sách comps thực hiện giống hoặc nhanh hơn so với gen. exprs (trên các ví dụ tôi đã thử). Đừng làm tối ưu hóa sớm trong mọi trường hợp. – jfs

+0

@JF, yep - Tôi ước rằng chỉ có MỘT cách rõ ràng để làm điều đó, nhưng, cho rằng, than ôi, có hai, danh sách thực sự nhanh hơn 'list (genexp)' (có khả năng bởi một yếu tố quan trọng) và nói chung nên được ưa thích khi cả hai hình thức có thể và "rõ ràng". –

+0

Dang! Tôi đứng sửa. Cảm ơn, JF và Alex. Quan niệm sai lầm của tôi về hiệu năng genexp được bắt nguồn từ thành ngữ Python có liên quan: sử dụng bất kỳ [bounded] nào lặp lại để tạo danh sách: newlist = list (x) nhanh hơn nhiều (và dễ đọc hơn) newlist = [y cho y in x] và vì genexps về cơ bản trả về một trình lặp, tôi giả định sai rằng danh sách (some_genexp) sẽ nhanh hơn danh sách tương ứng ... Bài học kinh nghiệm: Tôi sẽ sử dụng thời gian một cách có hệ thống hơn. BTW tất cả đều là lỗi của Alex! Tôi đã nhận được danh sách (x) thành ngữ từ Python cookBook. mjv

0

Này sẽ không được dễ dàng hơn:

(Tôi muốn một mảng 3 bit cao của một biến có chứa số nguyên 29)

dạng biến và mảng của bạn đầu tiên

a = ''

b = []

tôi lấy trộm này từ một ví dụ thực sự tốt trong diễn đàn này, nó định dạng số nguyên 29 thành 5 bit, bit zero throug h4 và đặt chuỗi bit vào biến chuỗi "a". [Sửa] cần thiết để thay đổi định dạng từ 0: 5b 0: 05b, để số không pad khi số nguyên là < 7.

a = '{0: 05b}'. Định dạng (29)

nhìn vào chuỗi của bạn biến

một

'11101'

chia chuỗi thành một mảng

b [0: 3] = a [0: 3]

đây chính xác là những gì tôi muốn.

b

[ '1', '1', '1']

1

Nếu bạn đang làm việc với xử lý dữ liệu thô của bất cứ loại nào, tôi muốn giới thiệu các mô-đun bitstring xuất sắc:

>>> import bitstring 
>>> bits = bitstring.Bits('0b110101001') 
>>> [b.uint for b in bits.cut(3)] 
[6, 5, 1] 

Mô tả từ home page:

Một mô-đun Python mà làm cho các creatio n, thao tác và phân tích dữ liệu nhị phân đơn giản và tự nhiên nhất có thể.

Bitstrings có thể được xây dựng từ số nguyên, phao, hex, bát phân, nhị phân, byte hoặc tệp. Chúng cũng có thể được tạo và diễn giải bằng cách sử dụng các chuỗi định dạng linh hoạt .

Bitstrings có thể được cắt, nối, đảo ngược, chèn vào, ghi đè, vv với các phương pháp đơn giản hoặc sử dụng ký hiệu slice. Họ cũng có thể được đọc, tìm kiếm và thay thế, và điều hướng trong, tương tự như một tệp hoặc luồng.

Nội bộ dữ liệu bit được lưu trữ hiệu quả trong mảng byte, mô-đun đã được tối ưu hóa cho tốc độ và phạm vi mã tuyệt vời là được cung cấp bởi hơn 400 bài kiểm tra đơn vị.

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