python - पायथन में दो-आयामी सरणी कैसे प्रारंभ करें?




9 Answers

पाइथन में अक्सर एक पैटर्न आया था

bar = []
for item in some_iterable:
    bar.append(SOME EXPRESSION)

जिसने सूची समझों की शुरूआत को प्रेरित करने में मदद की, जो उस स्निपेट को परिवर्तित करता है

bar = [SOME EXPRESSION for item in some_iterable]

जो छोटा और कभी-कभी स्पष्ट होता है। आम तौर पर आप इन्हें पहचानने की आदत में आते हैं और अक्सर समझ के साथ लूप को बदलते हैं।

आपका कोड दो बार इस पैटर्न का पालन करता है

twod_list = []                                       \                      
for i in range (0, 10):                               \
    new = []                  \ can be replaced        } this too
    for j in range (0, 10):    } with a list          /
        new.append(foo)       / comprehension        /
    twod_list.append(new)                           /

मैं अजगर शुरू कर रहा हूं और मैं एक द्वि-आयामी सूची का उपयोग करने की कोशिश कर रहा हूं, जिसे मैं शुरू में हर जगह एक ही चर के साथ भरता हूं। मैं इसके साथ आया:

def initialize_twodlist(foo):
    twod_list = []
    new = []
    for i in range (0, 10):
        for j in range (0, 10):
            new.append(foo)
        twod_list.append(new)
        new = []

यह वांछित परिणाम देता है, लेकिन एक कामकाज की तरह लगता है। क्या ऐसा करने के लिए एक आसान / छोटा / अधिक सुरुचिपूर्ण तरीका है?




इस तरह नेस्टेड सूची समझ से तेज है

[x[:] for x in [[foo] * 10] * 10]    # for immutable foo!

छोटी और बड़ी सूचियों के लिए यहां कुछ पायथन 3 समय दिए गए हैं

$python3 -m timeit '[x[:] for x in [[1] * 10] * 10]'
1000000 loops, best of 3: 1.55 usec per loop

$ python3 -m timeit '[[1 for i in range(10)] for j in range(10)]'
100000 loops, best of 3: 6.44 usec per loop

$ python3 -m timeit '[x[:] for x in [[1] * 1000] * 1000]'
100 loops, best of 3: 5.5 msec per loop

$ python3 -m timeit '[[1 for i in range(1000)] for j in range(1000)]'
10 loops, best of 3: 27 msec per loop

स्पष्टीकरण:

[[foo]*10]*10 एक ही वस्तु की एक सूची को 10 बार दोहराता है। आप इसका उपयोग नहीं कर सकते हैं, क्योंकि एक तत्व को संशोधित करने से प्रत्येक पंक्ति में उसी तत्व को संशोधित किया जाएगा!

x[:] list(X) बराबर है लेकिन यह थोड़ा अधिक कुशल है क्योंकि यह नाम लुकअप से बचाता है। किसी भी तरह से, यह प्रत्येक पंक्ति की उथली प्रति बनाता है, इसलिए अब सभी तत्व स्वतंत्र हैं।

हालांकि सभी तत्व एक ही foo ऑब्जेक्ट हैं, इसलिए यदि foo mutable है , तो आप इस योजना का उपयोग नहीं कर सकते हैं।, आपको इसका उपयोग करना होगा

import copy
[[copy.deepcopy(foo) for x in range(10)] for y in range(10)]

या एक कक्षा (या समारोह) Foo मानते हैं जो foo s देता है

[[Foo() for x in range(10)] for y in range(10)]



उपयोग न करें [[वी] * एन] * एन, यह एक जाल है!

>>> a = [[0]*3]*3
>>> a
[[0, 0, 0], [0, 0, 0], [0, 0, 0]]
>>> a[0][0]=1
>>> a
[[1, 0, 0], [1, 0, 0], [1, 0, 0]]

लेकिन टी = [[0] * 3 रेंज में (3)] 3 महान है




आम तौर पर जब आप बहुआयामी सरणी चाहते हैं तो आप सूचियों की एक सूची नहीं चाहते हैं, बल्कि एक numpy सरणी या संभवतः एक निर्देश चाहते हैं।

उदाहरण के लिए, numpy के साथ आप कुछ ऐसा करेंगे

import numpy
a = numpy.empty((10, 10))
a.fill(foo)



यदि यह एक दुर्लभ-आबादी वाली सरणी है, तो आप एक टुपल के साथ कुंजीपटल के उपयोग से बेहतर हो सकते हैं:

dict = {}
key = (a,b)
dict[key] = value
...



गलत दृष्टिकोण: [[कोई नहीं * एम] * एन]

>>> m, n = map(int, raw_input().split())
5 5
>>> x[0][0] = 34
>>> x
[[34, None, None, None, None], [34, None, None, None, None], [34, None, None, None, None], [34, None, None, None, None], [34, None, None, None, None]]
>>> id(x[0][0])
140416461589776
>>> id(x[3][0])
140416461589776

इस दृष्टिकोण के साथ, पायथन बाहरी स्तंभों के लिए अलग-अलग पता स्थान बनाने की अनुमति नहीं देता है और आपकी अपेक्षा से भिन्न दुर्व्यवहार का कारण बनता है।

सही दृष्टिकोण लेकिन अपवाद के साथ:

y = [[0 for i in range(m)] for j in range(n)]
>>> id(y[0][0]) == id(y[1][0])
False

यह अच्छा दृष्टिकोण है लेकिन अगर आप किसी के लिए डिफ़ॉल्ट मान सेट करते हैं तो अपवाद है

>>> r = [[None for i in range(5)] for j in range(5)]
>>> r
[[None, None, None, None, None], [None, None, None, None, None], [None, None, None, None, None], [None, None, None, None, None], [None, None, None, None, None]]
>>> id(r[0][0]) == id(r[2][0])
True

तो इस दृष्टिकोण का उपयोग करके अपना डिफ़ॉल्ट मान सही ढंग से सेट करें।

पूर्ण सही:

डबल लूप के माइक के जवाब का पालन करें।




@ अर्नब और @ माइक ने बताया, एक सरणी एक सूची नहीं है। कुछ मतभेद हैं 1) सरणी प्रारंभिकरण के दौरान निश्चित आकार हैं 2) सरणी आमतौर पर एक सूची की तुलना में कम संचालन का समर्थन करती हैं।

शायद ज्यादातर मामलों में एक ओवरकिल, लेकिन यहां एक बुनियादी 2 डी सरणी कार्यान्वयन है जो पाइथन ctypes (सी पुस्तकालयों) का उपयोग कर हार्डवेयर सरणी कार्यान्वयन लेता है

import ctypes
class Array:
    def __init__(self,size,foo): #foo is the initial value
        self._size = size
        ArrayType = ctypes.py_object * size
        self._array = ArrayType()
        for i in range(size):
            self._array[i] = foo
    def __getitem__(self,index):
        return self._array[index]
    def __setitem__(self,index,value):
        self._array[index] = value
    def __len__(self):
        return self._size

class TwoDArray:
    def __init__(self,columns,rows,foo):
        self._2dArray = Array(rows,foo)
        for i in range(rows):
            self._2dArray[i] = Array(columns,foo)

    def numRows(self):
        return len(self._2dArray)
    def numCols(self):
        return len((self._2dArray)[0])
    def __getitem__(self,indexTuple):
        row = indexTuple[0]
        col = indexTuple[1]
        assert row >= 0 and row < self.numRows() \
               and col >=0 and col < self.numCols(),\
               "Array script out of range"
        return ((self._2dArray)[row])[col]

if(__name__ == "__main__"):
    twodArray = TwoDArray(4,5,5)#sample input
    print(twodArray[2,3])



यहां एक आसान तरीका है:

import numpy as np
twoD = np.array([[]*m]*n)

किसी भी 'x' मान उपयोग के साथ सभी कोशिकाओं को प्रारंभ करने के लिए:

twoD = np.array([[x]*m]*n



अक्सर मैं 2-आयामी सरणी शुरू करने के लिए इस दृष्टिकोण का उपयोग करता हूं

n=[[int(x) for x in input().split()] for i in range(int(input())]




Related