पायथन में द्वि-आयामी सरणी को घुमाते हुए


122

एक कार्यक्रम में मैं दो-आयामी सरणी को घुमाने की आवश्यकता लिख ​​रहा हूं। इष्टतम समाधान की तलाश में मुझे यह प्रभावशाली एक-लाइनर मिला जो काम करता है:

rotated = zip(*original[::-1])

मैं इसे अपने कार्यक्रम में अब उपयोग कर रहा हूं और यह आवश्यकतानुसार काम करता है। हालांकि मेरी समस्या यह है कि मुझे समझ नहीं आता कि यह कैसे काम करता है।

अगर किसी को अलग-अलग कार्यों में वांछित परिणाम प्राप्त होता है, तो मैं कैसे समझा सकता हूं।


7
वास्तव में। मैं इसे इस एसओ प्रश्न में पाया ।
पालपाइंड

जवाबों:


96

निम्नलिखित दो आयामी सूची पर विचार करें:

original = [[1, 2],
            [3, 4]]

इसे चरण दर चरण तोड़ें:

>>> original[::-1]   # elements of original are reversed
[[3, 4], [1, 2]]

इस सूची को तर्क अनपैकिंगzip() का उपयोग करते हुए पारित किया जाता है , इसलिए कॉल इस के समतुल्य होता है:zip

zip([3, 4],
    [1, 2])
#    ^  ^----column 2
#    |-------column 1
# returns [(3, 1), (4, 2)], which is a original rotated clockwise

उम्मीद है कि टिप्पणियां स्पष्ट करती हैं कि यह क्या zipकरता है, यह सूचकांक के आधार पर प्रत्येक इनपुट से तत्वों को समूहित करेगा, या दूसरे शब्दों में यह कॉलम को समूहित करेगा।


2
एक करीब। लेकिन मैंने साफ ASCII कला के कारण आपका चयन किया;)
1948 में

1
और तारांकन ??
जॉन ktejik

@johnktejik - यह जवाब का "तर्क अनपैकिंग" हिस्सा है, विवरण के लिए लिंक पर क्लिक करें
JR हर्ड

1
स्पष्टता के लिए, आपको यह इंगित करना चाहिए कि यह मैट्रिक्स को दक्षिणावर्त घुमाता है और मूल से सूचियों को ट्यूपल्स में बदल दिया जाता है।
एवरेट

1
पूर्ण चक्र पर जाने के लिए (सूचियों की एक सूची प्राप्त करें और ट्यूपल्स नहीं) मैंने ऐसा किया:rotated = [list(r) for r in zip(*original[::-1])]
मैट

94

यह एक चतुर बिट है।

सबसे पहले, जैसा कि एक टिप्पणी में उल्लेख किया गया है, पायथन 3 में zip()एक पुनरावृत्त रिटर्न देता है, इसलिए आपको list()एक वास्तविक सूची वापस पाने के लिए पूरी चीज़ को संलग्न करने की आवश्यकता है , इसलिए 2020 तक यह वास्तव में है:

list(zip(*original[::-1]))

यहाँ ब्रेकडाउन है:

  • [::-1]- उल्टे क्रम में मूल सूची की उथली प्रति बनाता है। यह भी उपयोग कर सकता है reversed()जो वास्तव में सूची (अधिक मेमोरी कुशल) की नकल करने के बजाय सूची पर एक रिवर्स पुनरावृत्ति उत्पन्न करेगा।
  • *- प्रत्येक सूची को मूल सूची में एक अलग तर्क देता है zip()(यानी, सूची को हटाता है)
  • zip()- प्रत्येक तर्क से एक आइटम लेता है और उन लोगों से एक सूची (अच्छी तरह से, एक टुपल) बनाता है और तब तक दोहराता है जब तक कि सभी उपनलिस्ट समाप्त नहीं हो जाते हैं। यह वह जगह है जहाँ वाष्पोत्सर्जन वास्तव में होता है।
  • list()zip()एक सूची के उत्पादन धर्मान्तरित ।

तो यह मानते हुए कि आपके पास यह है:

[ [1, 2, 3],
  [4, 5, 6],
  [7, 8, 9] ]

आप पहले इसे प्राप्त करें (उथले, उलट प्रति):

[ [7, 8, 9],
  [4, 5, 6],
  [1, 2, 3] ]

अगले प्रत्येक उपविजेता को एक तर्क के रूप में पारित किया जाता है zip:

zip([7, 8, 9], [4, 5, 6], [1, 2, 3])

zip() बार-बार अपने प्रत्येक तर्क की शुरुआत से एक आइटम का उपभोग करता है और इससे एक नल बनाता है, जब तक कि अधिक आइटम न हों, जिसके परिणामस्वरूप (सूची में परिवर्तित होने के बाद):

[(7, 4, 1), 
 (8, 5, 2), 
 (9, 6, 3)]

और बॉब आपके चाचा हैं।

दूसरी दिशा में इसे घुमाने के बारे में एक टिप्पणी में @ IkeMiguel के प्रश्न का उत्तर देने के लिए, यह बहुत सीधा है: आपको बस उन दोनों दृश्यों को उलटने की आवश्यकता है zipजो परिणाम और परिणाम में जाते हैं। पहली को हटाकर हासिल किया जा सकता है [::-1]और दूसरे reversed()को पूरी चीज को फेंक कर हासिल किया जा सकता है। के बाद से reversed()रिटर्न सूची पर पुनरावर्तक, हम डाल करने की आवश्यकता होगी list()के आसपास है कि यह कन्वर्ट करने के लिए। कुछ अतिरिक्त list()कॉल के साथ पुनरावृत्तियों को एक वास्तविक सूची में बदलने के लिए। इसलिए:

rotated = list(reversed(list(zip(*original))))

हम इसके बजाय "मार्टियन स्माइली" स्लाइस का उपयोग करके इसे थोड़ा सरल कर सकते हैं reversed()... फिर हमें बाहरी की आवश्यकता नहीं है list():

rotated = list(zip(*original))[::-1]

बेशक, आप केवल तीन बार सूची को दक्षिणावर्त घुमा सकते हैं। :-)


2
क्या काउंटर क्लॉकवाइज घूमना संभव है ??
मिगुएल इके

@ मिगुएलइके हाँ, ज़िप करें (* मैट्रिक्स) [:: - 1]
RYS

3
^ ध्यान दें कि आपको zipपायथन 3.x में सूची का परिणाम डालना है !
RYS

17

इसके तीन भाग हैं:

  1. मूल [:: - 1] मूल सरणी को उलट देता है। यह संकेतन पायथन सूची स्लाइसिंग है। यह आपको [प्रारंभ: अंत: चरण] द्वारा वर्णित मूल सूची का एक "सबलिस्ट" प्रदान करता है, प्रारंभ पहला तत्व है, अंतिम अंतिम तत्व है जो सबलिस्ट में उपयोग किया जाता है। चरण कहता है कि पहले से अंतिम तक हर चरण तत्व को लें। प्रारंभ और अंत का मतलब है कि स्लाइस पूरी सूची होगी, और नकारात्मक कदम का मतलब है कि आपको तत्वों को उल्टा मिलेगा। इसलिए, उदाहरण के लिए, यदि मूल [x, y, z] था, तो परिणाम [z, y, x] होगा।
  2. किसी फ़ंक्शन कॉल की तर्क सूची में सूची / टपल से पहले * का अर्थ सूची / टपल का "विस्तार" करना है, ताकि इसके प्रत्येक तत्व सूची / ट्यूपल के बजाय फ़ंक्शन के लिए एक अलग तर्क बन जाए। ताकि, अगर, कहते हैं, args = [1,2,3], तो zip (args) zip ([1,2,3]) के समान है, लेकिन zip (* args) zip (1,) के समान है 2,3)।
  3. zip एक ऐसा फंक्शन है जो प्रत्येक के n तर्कों को लेता है, जो कि लंबाई m का है और लंबाई m की सूची का निर्माण करता है, तत्व n की लंबाई के हैं और इनमें से प्रत्येक मूल सूची के संगत तत्व हैं। जैसे, ज़िप ([१,२], [ए, बी], [एक्स, वाई]] [[१, ए, एक्स], [२, बी, वाई]] है। पायथन प्रलेखन भी देखें

+1 के बाद से आप शायद पहले चरण की व्याख्या कर रहे हैं।
पलडिपिंड

8

सिर्फ एक अवलोकन। इनपुट सूची की एक सूची है, लेकिन बहुत अच्छे समाधान से आउटपुट: घुमाया = ज़िप (* मूल [:: - 1]) tuples की एक सूची देता है।

यह एक मुद्दा हो सकता है या नहीं भी हो सकता है।

हालाँकि, यह आसानी से सुधारा जाता है:

original = [[1, 2, 3],
            [4, 5, 6],
            [7, 8, 9]
            ]


def rotated(array_2d):
    list_of_tuples = zip(*array_2d[::-1])
    return [list(elem) for elem in list_of_tuples]
    # return map(list, list_of_tuples)

print(list(rotated(original)))

# [[7, 4, 1], [8, 5, 2], [9, 6, 3]]

सूची COMP या मानचित्र दोनों आंतरिक tuples को सूचियों में बदल देंगे।


2
def ruota_orario(matrix):
   ruota=list(zip(*reversed(matrix)))
   return[list(elemento) for elemento in ruota]
def ruota_antiorario(matrix):
   ruota=list(zip(*reversed(matrix)))
   return[list(elemento)[::-1] for elemento in ruota][::-1]

4
कृपया अपने समाधान की व्याख्या करें ताकि अन्य इसे बेहतर समझ सकें।
हेलोस्पीकमैन

बेशक, पहला फ़ंक्शन (ruota_antiorario) वामावर्त में वामावर्त और दूसरा फ़ंक्शन (ruota_orario)
घुमाता है

1

मुझे स्वयं यह समस्या है और मुझे इस विषय पर ("सामान्य घुमाव" पैराग्राफ में महान विकिपीडिया पृष्ठ मिला है:
https://en.wikipedia.org/wiki/Rotation_matrix#Ambiguities

फिर मैंने निम्नलिखित कोड, सुपर वर्बोज़ लिखा, ताकि जो कुछ हो रहा है उसकी स्पष्ट समझ हो।

मुझे आशा है कि आपके द्वारा पोस्ट किए गए बहुत सुंदर और चतुर एक-लाइनर को खोदने में आपको उपयोगी लगेगा।

इसे जल्दी से परखने के लिए आप इसे यहाँ कॉपी / पेस्ट कर सकते हैं: http : //www.codesk मूर्तिकार
ओआर /

triangle = [[0,0],[5,0],[5,2]]
coordinates_a = triangle[0]
coordinates_b = triangle[1]
coordinates_c = triangle[2]

def rotate90ccw(coordinates):
    print "Start coordinates:"
    print coordinates
    old_x = coordinates[0]
    old_y = coordinates[1]
# Here we apply the matrix coming from Wikipedia
# for 90 ccw it looks like:
# 0,-1
# 1,0
# What does this mean?
#
# Basically this is how the calculation of the new_x and new_y is happening:
# new_x = (0)(old_x)+(-1)(old_y)
# new_y = (1)(old_x)+(0)(old_y)
#
# If you check the lonely numbers between parenthesis the Wikipedia matrix's numbers
# finally start making sense.
# All the rest is standard formula, the same behaviour will apply to other rotations, just
# remember to use the other rotation matrix values available on Wiki for 180ccw and 170ccw
    new_x = -old_y
    new_y = old_x
    print "End coordinates:"
    print [new_x, new_y]

def rotate180ccw(coordinates):
    print "Start coordinates:"
    print coordinates
    old_x = coordinates[0]
    old_y = coordinates[1] 
    new_x = -old_x
    new_y = -old_y
    print "End coordinates:"
    print [new_x, new_y]

def rotate270ccw(coordinates):
    print "Start coordinates:"
    print coordinates
    old_x = coordinates[0]
    old_y = coordinates[1]  
    new_x = -old_x
    new_y = -old_y
    print "End coordinates:"
    print [new_x, new_y]

print "Let's rotate point A 90 degrees ccw:"
rotate90ccw(coordinates_a)
print "Let's rotate point B 90 degrees ccw:"
rotate90ccw(coordinates_b)
print "Let's rotate point C 90 degrees ccw:"
rotate90ccw(coordinates_c)
print "=== === === === === === === === === "
print "Let's rotate point A 180 degrees ccw:"
rotate180ccw(coordinates_a)
print "Let's rotate point B 180 degrees ccw:"
rotate180ccw(coordinates_b)
print "Let's rotate point C 180 degrees ccw:"
rotate180ccw(coordinates_c)
print "=== === === === === === === === === "
print "Let's rotate point A 270 degrees ccw:"
rotate270ccw(coordinates_a)
print "Let's rotate point B 270 degrees ccw:"
rotate270ccw(coordinates_b)
print "Let's rotate point C 270 degrees ccw:"
rotate270ccw(coordinates_c)
print "=== === === === === === === === === "

-1

सूची और डिक्ट के रूप में काउंटर क्लॉकवाइज़ (पंक्ति पिवट के लिए मानक कॉलम) को घुमाएगी

rows = [
  ['A', 'B', 'C', 'D'],
  [1,2,3,4],
  [1,2,3],
  [1,2],
  [1],
]

pivot = []

for row in rows:
  for column, cell in enumerate(row):
    if len(pivot) == column: pivot.append([])
    pivot[column].append(cell)

print(rows)
print(pivot)
print(dict([(row[0], row[1:]) for row in pivot]))

पैदा करता है:

[['A', 'B', 'C', 'D'], [1, 2, 3, 4], [1, 2, 3], [1, 2], [1]]
[['A', 1, 1, 1, 1], ['B', 2, 2, 2], ['C', 3, 3], ['D', 4]]
{'A': [1, 1, 1, 1], 'B': [2, 2, 2], 'C': [3, 3], 'D': [4]}

1
यह प्रश्न से संबंधित नहीं है, जो यह बताता है कि कैसे zip(*original[::-1])काम करता है।
काया 3
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.