2013-01-29 5 views
6

में अधिकतम आकार से अधिक की सूची बनाने के लिए कैसे करें this, 32 बिट सिस्टम पर पाइथन सूची का अधिकतम आकार 536,870,912 तत्व है।पाइथन

क्या इससे बड़ा आकार वाले सूची को शुरू करने का कोई संभावित तरीका है?

मान लीजिए:

list1 = [None]*1000000000 
+3

ठीक है, नहीं, कि क्या एक "अधिकतम आकार" का अर्थ है। यदि आप स्मृति रखते हैं, तो आप अनुमान लगा सकते हैं कि आप एक साथ समूह का एक गुच्छा 'itertools.chain' कर सकते हैं। –

+3

क्या आपने ध्यान दिया कि सूची के प्रत्येक तत्व, कम से कम, 4 बाइट्स पर कब्जा करते हैं, इस प्रकार '4 * 536,870,912 = 2147483648'। अब सूची के लिए 2 जीबी रैम है। यदि तत्व समान नहीं हैं तो मुझे पूरा यकीन है कि आपको उस आकार तक पहुंचने से पहले मेमोरी त्रुटि मिल जाएगी। – Bakuriu

+1

@bakuriu आपको इंगित करने के लिए धन्यवाद। मुझे एक मेमोरी एरर मिला। :( –

उत्तर

10

सूचियाँ कि बड़े ऊपर अंतरिक्ष के एक बड़े पैमाने पर राशि, अधिकतम स्वीकृत तत्वों के साथ तो बस एक सूची ले जाएगा के रूप में सूची में प्रत्येक तत्व कम से कम 4 बाइट्स का स्थान लेगा, ऊपर ले जाएगा न्यूनतम 2 जीबी रैम । और यह 64-बिट सिस्टम पर विचार किए बिना भी है।

  1. 4 * 5.4e+8 = 2.1e+9, 2.1 जीबी
  2. 8 * 1.2e+18 = 9.2+18, 9.2 ईबी (हाँ, एक्साबाइट)

हालांकि, प्रश्न के लिए, मान लें कि आप राम का एक बहुत है कि करते हैं।


सबसे आसान विकल्पों में से एक है विशाल सूची को पकड़ने और संभालने के लिए आपको अपना ऑब्जेक्ट बनाना होगा। यह मूल रूप से बड़ी सूची में छोटी सूची में विभाजित होगा, और फिर आवश्यकता होने पर तदनुसार उन्हें एक्सेस करेगा। चूंकि no real benefits of subclassing list हैं क्योंकि आपको वैसे भी सभी विधियों को फिर से लिखना होगा, आप object को उप-वर्गीकृत करने के बेहतर होंगे और फिर वहां से जाएं। यहां केवल एक चीज है जो उप-सूचियों को कभी गठबंधन या प्रतिलिपि नहीं करना है (क्योंकि वे बड़े पैमाने पर हैं), इसलिए आवश्यक होने पर सूचियों पर लूप के लिए itertools.chain का उपयोग करें।

यहाँ सबसे सरल सूची-तरीकों का एक उदाहरण है append, extend, get/setitem काम कर रहे:

import sys 
from itertools import chain 

class largeList(object): 
    def __init__(self, mylist=[]): 
     self.maxSize = sys.maxsize/4 
     self.src = [[]] 
     self.extend(mylist) 

    def __iter__(self): 
     return chain(*self.src) 

    def __getitem__(self, idx): 
     return self.src[int(idx/self.maxSize)][idx%self.maxSize] 

    def __setitem__(self, idx, item): 
     self.src[int(idx/self.maxSize)][idx%self.maxSize] = item 
     # expand set/getitem to support negative indexing. 

    def append(self, item): 
     if len(self.src[-1]) < self.maxSize: 
      self.src[-1].append(item) 
     else: 
      self.src.append([item]) 

    def extend(self, items): 
     remainder = self.maxSize - len(self.src[-1]) 
     self.src[-1].extend(items[:remainder]) 
     for i in xrange(0, len(items[remainder:]), self.maxSize): 
      self.src.append(items[remainder:][i:i+self.maxSize]) 

    def __len__(self): 
     return sum(len(l) for l in self.src) 

    def __str__(self): 
     size = self.__len__() 
     if size >= 8: 
      first, last = [], [] 
      for i, ele in enumerate(self.__iter__()): 
       if i < 3: 
        first.append(ele) 
       if i >= size - 3: 
        last.append(ele) 
      return str(first)[:-1] + ', ..., ' + str(last)[1:] 
     return str(list(self.__iter__())) 

उदाहरण का उपयोग करें (आप से 4 जीबी मुक्त रैम कम है या आप एक 64-बिट सिस्टम पर कर रहे हैं , इस प्रयास करने से पहले sys.maxsize बदलने):

#sys.maxsize = 1000 

list1 = largeList(xrange(sys.maxsize/4 + 2)) 
print len(list1) 
# 53687093 
print list1 
#[0, 1, 2, ..., 536870910, 536870911, 536870912] 
print list1.src 
#[[0, 1, 2 ..., 536870910], [536870911, 536870912]] 
list1.extend([42, 43]) 
print list1 
#[0, 1, 2, ..., 536870912, 42, 43] 

परिणाम: आंतरिक रूप से सूची, एकाधिक सूचियों में विभाजित हैं, जबकि वे जू प्रतीत उनके साथ काम करते समय सेंट एक। अधिक 0 जोड़कर अधिक list कार्यक्षमताओं को आसानी से जोड़ा जा सकता है। जैसे pop, remove, insert, और index:

(...) 

    def pop(self, idx): 
     listidx = int(idx/self.maxSize) 
     itempopped = self.src[listidx].pop(idx%self.maxSize) 
     for i in xrange(listidx, len(self.src)-1): 
      self.src[i].append(self.src[i+1].pop(0)) 
     if not self.src[-1]: 
      del self.src[-1] 
     return itempopped 

    def remove(self, item): 
     for i, ele in enumerate(self.__iter__()): 
      if ele == item: 
       self.pop(i) 
       break 

    def insert(self, idx, item): 
     listidx = int(idx/self.maxSize) 
     itemtoshift = self.src[listidx].pop(-1) 
     self.src[listidx].insert(idx%self.maxSize, item) 
     for i in xrange(listidx+1, len(self.src)-1): 
      itemremoved = self.src[i].pop(-1) 
      self.src[i].insert(0, itemtoshift) 
      itemtoshift = itemremoved 
     if len(self.src[-1]) < self.maxSize: 
      self.src[-1].insert(0, itemtoshift) 
     else: 
      self.src.append([self.src[-1].pop(-1)]) 
      self.src[-2].insert(0, itemtoshift) 

    def index(self, item): 
     for i, ele in enumerate(self.__iter__()): 
      if ele == item: 
       return i 
     return -1 

उदाहरण उपयोग करते हैं, जारी रखा:

#sys.maxsize = 1000 

list1 = largeList(xrange(sys.maxsize/4 + 2)) 
list1.insert(0, 'a') 
print list1 
#['a', 0, 1, ..., 536870910, 536870911, 536870912] 
list1.pop(2) 
#1 
list1.remove(536870910) 
print list1.index('a') 
#0 
print len(list1) 
#536870911 
print list1 
#['a', 0, 2, ..., 536870909, 536870911, 536870912] 
print list.src 
#[['a', 0, 2, ..., 536870909, 536870911], [536870912]]