Hướng dẫn dùng js zip python

Cập nhật năm 2016:

Đây là phiên bản Ecmascript 6 nhanh hơn:

zip= rows=>rows[0].map((_,c)=>rows.map(row=>row[c]))

Hình minh họa tương đương. sang Python { zip(*args)}:

> zip([['row0col0', 'row0col1', 'row0col2'],
       ['row1col0', 'row1col1', 'row1col2']]);
[["row0col0","row1col0"],
 ["row0col1","row1col1"],
 ["row0col2","row1col2"]]

(và FizzyTea chỉ ra rằng ES6 có cú pháp đối số khác nhau, vì vậy định nghĩa hàm sau đây sẽ hoạt động giống như python, nhưng hãy xem bên dưới để biết từ chối trách nhiệm ... điều này sẽ không phải là nghịch đảo của riêng nó vì vậy zip(zip(x))sẽ không bằng x; mặc dù như Matt Kramer đã chỉ ra zip(...zip(...x))==x(như trong python thông thường zip(*zip(*x))==x))

Định nghĩa thay thế tương đương. sang Python { zip}:

> zip = (...rows) => [...rows[0]].map((_,c) => rows.map(row => row[c]))
> zip( ['row0col0', 'row0col1', 'row0col2'] ,
       ['row1col0', 'row1col1', 'row1col2'] );
             // note zip(row0,row1), not zip(matrix)
same answer as above

(Xin lưu ý rằng ...cú pháp có thể có vấn đề về hiệu suất tại thời điểm này và có thể trong tương lai, vì vậy nếu bạn sử dụng câu trả lời thứ hai với các đối số khác nhau, bạn có thể muốn kiểm tra nó.)


Đây là oneliner:

function zip(arrays) {
    return arrays[0].map(function(_,i){
        return arrays.map(function(array){return array[i]})
    });
}

// > zip([[1,2],[11,22],[111,222]])
// [[1,11,111],[2,22,222]]]

// If you believe the following is a valid return value:
//   > zip([])
//   []
// then you can special-case it, or just do
//  return arrays.length==0 ? [] : arrays[0].map(...)

Ở trên giả định rằng các mảng có kích thước bằng nhau. Nó cũng giả sử bạn truyền vào một danh sách đối số danh sách, không giống như phiên bản của Python trong đó danh sách đối số là khác nhau. Nếu bạn muốn có tất cả các "tính năng" này, hãy xem bên dưới. Nó chỉ mất khoảng 2 dòng mã bổ sung.

Phần sau sẽ bắt chước ziphành vi của Python trong các trường hợp cạnh trong đó các mảng không có kích thước bằng nhau, giả vờ như các phần dài hơn của mảng không tồn tại:

function zip() {
    var args = [].slice.call(arguments);
    var shortest = args.length==0 ? [] : args.reduce(function(a,b){
        return a.length zip([1,2],[11,22],[111,222,333])
// [[1,11,111],[2,22,222]]]

// > zip()
// []

Điều này sẽ bắt chước itertools.zip_longesthành vi của Python , chèn vào undefinednơi các mảng không được xác định:

function zip() {
    var args = [].slice.call(arguments);
    var longest = args.reduce(function(a,b){
        return a.length>b.length ? a : b
    }, []);

    return longest.map(function(_,i){
        return args.map(function(array){return array[i]})
    });
}

// > zip([1,2],[11,22],[111,222,333])
// [[1,11,111],[2,22,222],[null,null,333]]

// > zip()
// []

Nếu bạn sử dụng hai phiên bản cuối cùng này (phiên bản đa đối số còn gọi là. Đa đối số), thì zip không còn là nghịch đảo của chính nó nữa. Để bắt chước zip(*[...])thành ngữ từ Python, bạn sẽ cần phải làm zip.apply(this, [...])khi bạn muốn đảo ngược hàm zip hoặc nếu bạn muốn tương tự có một số danh sách thay đổi làm đầu vào.


phụ lục :

Để làm cho xử lý này có thể lặp lại bất kỳ (ví dụ: trong Python, bạn có thể sử dụng ziptrên chuỗi, phạm vi, đối tượng bản đồ, v.v.), bạn có thể xác định như sau:

function iterView(iterable) {
    // returns an array equivalent to the iterable
}

Tuy nhiên, nếu bạn viết ziptheo cách sau , thậm chí điều đó sẽ không cần thiết:

function zip(arrays) {
    return Array.apply(null,Array(arrays[0].length)).map(function(_,i){
        return arrays.map(function(array){return array[i]})
    });
}

Bản giới thiệu:

> JSON.stringify( zip(['abcde',[1,2,3,4,5]]) )
[["a",1],["b",2],["c",3],["d",4],["e",5]]

(Hoặc bạn có thể sử dụng một range(...)hàm kiểu Python nếu bạn đã viết một hàm rồi. Cuối cùng, bạn sẽ có thể sử dụng trình tạo hoặc trình tạo mảng ECMAScript.)

199 hữu ích 5 bình luận chia sẻ

Vietnamese (Tiếng Việt) translation by Dai Phong (you can also view the original English article)

Nếu bạn đã từng sử dụng máy tính, bạn có thể đã bắt gặp các tập tin với phần mở rộng .zip. Chúng là các tập tin đặc biệt có thể chứa nội dung được nén của nhiều tập tin, thư mục và thư mục con khác. Điều này giúp chúng được truyền tải trên trên internet một cách dễ dàng. Bạn có biết rằng bạn có thể sử dụng Python để nén hoặc giải nén tập tin?

Bài này sẽ hướng dẫn bạn cách làm thế nào để sử dụng mô-đun zipfile trong Python, để giải nén hoặc nén từng tập tin hay nhiều tập tin cùng một lúc.

Nén các Tập tin Riêng lẻ

Cái này thì dễ và đòi hỏi rất ít code. Chúng ta bắt đầu bằng cách import mô-đun zipfile và sau đó mở đối tượng ZipFile trong chế độ ghi bằng cách chỉ định tham số thứ hai là 'w'. Tham số đầu tiên là đường dẫn đến chính tập tin. Đây là code mà bạn cần:

import zipfile
      
jungle_zip = zipfile.ZipFile('C:\\Stories\\Fantasy\\jungle.zip', 'w')
jungle_zip.write('C:\\Stories\\Fantasy\\jungle.pdf', compress_type=zipfile.ZIP_DEFLATED)

jungle_zip.close()

Xin lưu ý rằng tôi sẽ chỉ định đường dẫn trong tất cả các đoạn code theo một định dạng kiểu Windows; bạn sẽ cần phải thay đổi phù hợp nếu bạn đang ở trên Linux hoặc Mac.

Bạn có thể chỉ định các phương thức nén khác nhau để nén các tập tin. Các phương thức mới hơn BZIP2LZMA được bổ sung trong Python phiên bản 3.3, và còn có một số công cụ khác mà không hỗ trợ hai phương thức nén này. Vì lý do này, yên tâm khi chỉ cần sử dụng phương thức DEFLATED. Bạn cũng nên thử những phương thức này để thấy sự khác biệt trong kích thước của các tập tin nén.

Nén nhiều Tập tin

Điều này hơi phức tạp một chút vì bạn cần lặp qua tất cả các tập tin. Code dưới đây sẽ nén tất cả các tập tin với phần mở rộng tập tin pdf trong một thư mục nhất định:

import os
import zipfile

fantasy_zip = zipfile.ZipFile('C:\\Stories\\Fantasy\\archive.zip', 'w')

for folder, subfolders, files in os.walk('C:\\Stories\\Fantasy'):

    for file in files:
        if file.endswith('.pdf'):
            fantasy_zip.write(os.path.join(folder, file), os.path.relpath(os.path.join(folder,file), 'C:\\Stories\\Fantasy'), compress_type = zipfile.ZIP_DEFLATED)

fantasy_zip.close()

Lần này, chúng ta đã import mô-đun os và sử dụng phương thức walk() của nó để duyệt qua tất cả các tập tin và thư mục con trong thư mục gốc của chúng ta. Tôi chỉ nén các tập tin pdf trong thư mục. Bạn cũng có thể tạo các tập tin lưu trữ khác cho mỗi định dạng bằng cách sử dụng câu lệnh if.

Nếu bạn không muốn giữ lại cấu trúc thư mục, bạn có thể gom tất cả các tập tin với nhau bằng cách sử dụng dòng code sau:

fantasy_zip.write(os.path.join(folder, file), file, compress_type = zipfile.ZIP_DEFLATED)

Phương thức write() chấp nhận ba tham số. Tham số đầu tiên là tên tập tin mà chúng ta muốn nén. Tham số thứ hai là không bắt buộc và cho phép bạn chỉ định một tên tập tin khác cho tập tin được nén. Nếu không được chỉ định, thì tên ban đầu được sử dụng.

Giải nén tất cả các Tập tin

Bạn có thể sử dụng phương thức extractall() để giải nén tất cả các tập tin và thư mục từ một tập tin nén vào thư mục hiện tại. Bạn cũng có thể truyền một tên thư mục vào extractall() để giải nén các tập tin và thư mục trong một thư mục cụ thể. Nếu thư mục mà bạn truyền vào không tồn tại, phương thức này sẽ tạo nó cho bạn. Dưới đây là đoạn code bạn có thể sử dụng để giải nén các tập tin:

import zipfile
    	
fantasy_zip = zipfile.ZipFile('C:\\Stories\\Fantasy\\archive.zip')
fantasy_zip.extractall('C:\\Library\\Stories\\Fantasy')

fantasy_zip.close()

Nếu bạn muốn giải nén nhiều tập tin, bạn sẽ phải cung cấp tên của các tập tin mà bạn muốn giải nén dưới dạng một danh sách.

Giải nén từng Tập tin

Điều này cũng tương tự như giải nén nhiều tập tin. Một sự khác biệt là lần này, bạn cần phải cung cấp tên tập tin đầu tiên và đường dẫn để giải nén chúng vào đó. Ngoài ra, bạn cần phải sử dụng phương thức extract() thay vì extractall(). Dưới đây là một đoạn code cơ bản để giải nén từng tập tin.

import zipfile
    	
fantasy_zip = zipfile.ZipFile('C:\\Stories\\Fantasy\\archive.zip')
fantasy_zip.extract('Fantasy Jungle.pdf', 'C:\\Stories\\Fantasy')

fantasy_zip.close()

Đọc các Tập tin Zip

Hãy xem xét một trường hợp mà bạn cần xem một tập tin lưu trữ zip có chứa một tập tin cụ thể nào đó hay không. Đến thời điểm này, lựa chọn duy nhất của bạn để làm điều đó là bằng cách giải nén tất cả các tập tin trong kho lưu trữ. Tương tự, bạn có thể cần phải giải nén chỉ những tập tin đó mà lớn hơn một kích thước cụ thể. Mô-đun zipfile cho phép chúng ta kiểm tra nội dung của một tập tin nén mà không cần giải nén nó.

Sử dụng phương thức namelist() của đối tượng ZipFile sẽ trả về một danh sách tất cả các thành phần của một tập tin nén theo tên. Để có được thông tin về một tập tin cụ thể trong tập tin nén, bạn có thể sử dụng phương thức getinfo() của đối tượng ZipFile. Điều này sẽ cho phép bạn truy cập vào thông tin cụ thể đối với tập tin đó, giống như kích thước nén và chưa nén của tập tin hoặc lần sửa đổi cuối cùng của nó. Chúng ta sẽ quay trở lại điều đó sau.

Gọi phương thức getinfo() từng cái một trên tất cả các tập tin có thể là một quá trình nhọc nhằn khi có rất nhiều tập tin cần phải được xử lý. Trong trường hợp này, bạn có thể sử dụng phương thức infolist() để trả về một danh sách có chứa một đối tượng ZipInfo cho mỗi thành phần trong tập tin nén. Thứ tự của các đối tượng này trong danh sách là giống với các tập tin zip thật sự.

Bạn cũng có thể trực tiếp đọc nội dung của một tập tin cụ thể từ tập tin nén bằng cách sử dụng phương thức read(file), trong đó file là tên của tập tin bạn muốn đọc. Để làm điều này, tập tin nén phải được mở trong chế độ đọc hoặc nối thêm.

Để có được kích thước nén của một tập tin riêng biệt từ tập tin nén, bạn có thể sử dụng thuộc tính compress_size. Tương tự như vậy, để biết kích thước chưa nén, bạn có thể sử dụng thuộc tính file_size.

Code sau đây sử dụng các thuộc tính và phương thức mà chúng ta vừa mới thảo luận để giải nén chỉ những tập tin có kích thước dưới 1MB.

import zipfile

stories_zip = zipfile.ZipFile('C:\\Stories\\Funny\\archive.zip')

for file in stories_zip.namelist():
    if stories_zip.getinfo(file).file_size < 1024*1024:
		stories_zip.extract(file, 'C:\\Stories\\Short\\Funny')
        
stories_zip.close()

Để biết ngày và giờ khi một tập tin cụ thể từ tập tin nén bị sửa đổi gần đây nhất, bạn có thể sử dụng thuộc tính date_time. Điều này sẽ trả về một tuple gồm sáu giá trị. Các giá trị sẽ là năm, tháng, ngày, giờ, phút và giây, theo thứ tự cụ thể đó. Năm sẽ luôn luôn được lớn hơn hoặc bằng năm 1980, và giờ, phút và giây là bắt đầu từ 0.

import zipfile

stories_zip = zipfile.ZipFile('C:\\Stories\\Funny\\archive.zip')

thirsty_crow_info = stories_zip.getinfo('The Thirsty Crow.pdf')

print(thirsty_crow_info.date_time)
print(thirsty_crow_info.compress_size)
print(thirsty_crow_info.file_size)
        
stories_zip.close()

Thông tin về kích thước tập tin gốc và kích thước tập tin nén có thể giúp bạn quyết định có nên nén một tập tin hay không. Tôi chắc rằng nó cũng có thể được sử dụng trong một số trường khác.

Tổng kết

Rõ ràng, sử dụng mô-đun zipfile để nén tập tin cung cấp cho bạn rất nhiều tính linh hoạt. Bạn có thể nén các tập tin khác nhau trong một thư mục thành các tập tin nén khác nhau dựa trên loại, tên hoặc kích thước của chúng. Bạn cũng có thể quyết định xem bạn có muốn giữ lại cấu trúc thư mục hay không. Tương tự, khi giải nén các tập tin, bạn có thể giải nén chúng đến vị trí bạn muốn, dựa trên tiêu chí riêng của bạn như kích thước, vv.

Thật tình, tôi thấy cũng khá thú vị khi nén và giải nén tập tin bằng cách viết code của riêng mình. Tôi hy vọng bạn thích hướng dẫn này, và nếu bạn có bất kỳ câu hỏi nào, xin vui lòng cho tôi biết trong phần bình luận nhé.