भोला दृष्टिकोण
def transpose_finite_iterable(iterable):
return zip(*iterable) # `itertools.izip` for Python 2 users
परिमित पुनरावृत्ति के लिए ठीक काम करता है (उदाहरण के लिए list
/ tuple
/ str
) (संभावित अनंत) पुनरावृत्तियों की तरह जो कि इसका वर्णन किया जा सकता है
| |a_00| |a_10| ... |a_n0| |
| |a_01| |a_11| ... |a_n1| |
| |... | |... | ... |... | |
| |a_0i| |a_1i| ... |a_ni| |
| |... | |... | ... |... | |
कहाँ पे
n in ℕ
,
a_ij
j
-th तत्व के अनुरूप है i
,
और आवेदन करने के बाद transpose_finite_iterable
हम प्राप्त करते हैं
| |a_00| |a_01| ... |a_0i| ... |
| |a_10| |a_11| ... |a_1i| ... |
| |... | |... | ... |... | ... |
| |a_n0| |a_n1| ... |a_ni| ... |
ऐसे मामले का पायथन उदाहरण जहां a_ij == j
,n == 2
>>> from itertools import count
>>> iterable = [count(), count()]
>>> result = transpose_finite_iterable(iterable)
>>> next(result)
(0, 0)
>>> next(result)
(1, 1)
लेकिन हम transpose_finite_iterable
फिर से मूल की संरचना में लौटने के लिए उपयोग नहीं कर सकते iterable
क्योंकि result
परिमित पुनरावृत्तियों की एक अनंत पुनरावृत्ति है ( tuple
हमारे मामले में):
>>> transpose_finite_iterable(result)
... hangs ...
Traceback (most recent call last):
File "...", line 1, in ...
File "...", line 2, in transpose_finite_iterable
MemoryError
तो हम इस मामले से कैसे निपट सकते हैं?
... और यहाँ आता है deque
जब हम itertools.tee
फ़ंक्शन के डॉक्स पर एक नज़र डालते हैं , तो पायथन नुस्खा है जो कुछ संशोधन के साथ हमारे मामले में मदद कर सकता है
def transpose_finite_iterables(iterable):
iterator = iter(iterable)
try:
first_elements = next(iterator)
except StopIteration:
return ()
queues = [deque([element])
for element in first_elements]
def coordinate(queue):
while True:
if not queue:
try:
elements = next(iterator)
except StopIteration:
return
for sub_queue, element in zip(queues, elements):
sub_queue.append(element)
yield queue.popleft()
return tuple(map(coordinate, queues))
चलो देखते है
>>> from itertools import count
>>> iterable = [count(), count()]
>>> result = transpose_finite_iterables(transpose_finite_iterable(iterable))
>>> result
(<generator object transpose_finite_iterables.<locals>.coordinate at ...>, <generator object transpose_finite_iterables.<locals>.coordinate at ...>)
>>> next(result[0])
0
>>> next(result[0])
1
संश्लेषण
अब हम पुनरावृत्तियों के पुनरावृत्तियों के साथ काम करने के लिए सामान्य कार्य को परिभाषित कर सकते हैं, जिनमें से परिमित हैं और एक अन्य संभावित रूप से functools.singledispatch
सजावट की तरह अनंत हैं
from collections import (abc,
deque)
from functools import singledispatch
@singledispatch
def transpose(object_):
"""
Transposes given object.
"""
raise TypeError('Unsupported object type: {type}.'
.format(type=type))
@transpose.register(abc.Iterable)
def transpose_finite_iterables(object_):
"""
Transposes given iterable of finite iterables.
"""
iterator = iter(object_)
try:
first_elements = next(iterator)
except StopIteration:
return ()
queues = [deque([element])
for element in first_elements]
def coordinate(queue):
while True:
if not queue:
try:
elements = next(iterator)
except StopIteration:
return
for sub_queue, element in zip(queues, elements):
sub_queue.append(element)
yield queue.popleft()
return tuple(map(coordinate, queues))
def transpose_finite_iterable(object_):
"""
Transposes given finite iterable of iterables.
"""
yield from zip(*object_)
try:
transpose.register(abc.Collection, transpose_finite_iterable)
except AttributeError:
# Python3.5-
transpose.register(abc.Mapping, transpose_finite_iterable)
transpose.register(abc.Sequence, transpose_finite_iterable)
transpose.register(abc.Set, transpose_finite_iterable)
जिसे अपने स्वयं के व्युत्क्रम के रूप में माना जा सकता है (गणितज्ञ इस तरह के कार्यों को "इनवोल्यूशन" कहते हैं ) परिमित गैर-खाली पुनरावृत्तियों पर बाइनरी ऑपरेटरों की श्रेणी में आते हैं।
singledispatch
आईएनजी के एक बोनस के रूप में हम numpy
सरणियों को संभाल सकते हैं जैसे
import numpy as np
...
transpose.register(np.ndarray, np.transpose)
और फिर इसका उपयोग करें
>>> array = np.arange(4).reshape((2,2))
>>> array
array([[0, 1],
[2, 3]])
>>> transpose(array)
array([[0, 2],
[1, 3]])
ध्यान दें
के बाद से transpose
रिटर्न iterators और अगर किसी को एक करने की है tuple
की list
ओपी में की तरह रों - इस के साथ साथ ही बनाया जा सकता है map
में निर्मित समारोह की तरह
>>> original = [('a', 1), ('b', 2), ('c', 3), ('d', 4)]
>>> tuple(map(list, transpose(original)))
(['a', 'b', 'c', 'd'], [1, 2, 3, 4])
विज्ञापन
मैंने सामान्यीकृत समाधान को संस्करण से lz
पैकेज में जोड़ा है 0.5.0
जिसका उपयोग किया जा सकता है
>>> from lz.transposition import transpose
>>> list(map(tuple, transpose(zip(range(10), range(10, 20)))))
[(0, 1, 2, 3, 4, 5, 6, 7, 8, 9), (10, 11, 12, 13, 14, 15, 16, 17, 18, 19)]
पुनश्च
संभावित अनंत पुनरावृत्तियों के संभावित अनंत से निपटने के लिए कोई समाधान (कम से कम स्पष्ट) नहीं है, लेकिन यह मामला हालांकि कम आम है।