2012-09-20 14 views
9

यहां स्थिति है:
मेरे पास सूची है जो वास्तव में संख्याओं को स्टोर करती है और बहुत बड़ी हो सकती है (लाखों आइटम)।
मैं संख्याओं को स्ट्रिंग के रूप में संग्रहीत करता हूं क्योंकि पाठ की कुछ अतिरिक्त जानकारी प्रदर्शित करने का विकल्प होता है।स्थानांतरित करने के साथ सूची का प्रबंधन करने का सबसे अच्छा तरीका

क्योंकि स्टोर करने के लिए बहुत सारी मेमोरी लेती है, मैंने फैसला किया कि मैं केवल अधिकतम 5 मिलियन आइटम स्टोर करूंगा। (इसमें केवल 250-300 एमबी लगेगा)।

सूची गणना के आउटपुट से भरा है। यदि कोई संख्या पाई जाती है तो इसे सूची में जोड़ा जाएगा, यह संख्या मौजूदा वस्तुओं की तुलना में हमेशा बड़ी है।

जब सूची 5 मिलियन तक पहुंच गई तो मैं पहली वस्तु को हटाना चाहता हूं और सूची में नया आइटम जोड़ना चाहता हूं।

चाहते:

// Why is this so freaking slow??? 
    if (_result.Count == 5000000) 
     _result.RemoveAt(0); 
    _result.Add(result); 

आप टिप्पणी में पढ़ा सकते हैं, यह बहुत, बहुत, बहुत धीमी है। यह सिर्फ 15 बार मेरे प्रदर्शन में कटौती। इसमें 2 मिनट लग गए, अब इसमें लगभग 30.

मैंने .Skip(1).ToList जैसे लिनक के साथ कुछ चीजों की कोशिश की लेकिन यह सूची को फिर से बनाएगा और इसलिए यह और भी धीमी है।

सूची सही क्रम में रहनी चाहिए, इसलिए इंडेक्स द्वारा ओवरराइटिंग एक विकल्प नहीं है (जब तक आप चारों ओर एक अच्छा काम समझा नहीं सकते)।

मेरा प्रश्न:
क्या ऐसा करने का कोई अच्छा तरीका है?

मुझे वास्तव में यहां प्रदर्शन की आवश्यकता है क्योंकि इसे 10000000000 नंबरों की जांच करने की आवश्यकता हो सकती है। यह एक दिन बिल्कुल लग सकता है, लेकिन एक महीने में थोड़ा बहुत ज्यादा :(है

, में अतिरिक्त जानकारी चाहिए पूछने के लिए स्वतंत्र महसूस हो रहा है, मैं की आपूर्ति करने में प्रसन्नता होगी

समाधान:।।
यह प्रदर्शन करती हे (1)

// Set the _result 
    Queue<object> _result = new Queue<object>(5000000); 

    /// Inside the method 
    // If the count has reach it's max, dequeue the first item 
    if (_result.Count == 5000000) 
     _result.Dequeue(); 
    _result.Enqueue(result); 
+0

क्या कोई अनिवार्य कारण है कि आपको एक सूची का उपयोग करना है? क्या आप – swiftgp

+0

@ user1556110 के बजाय SQLite डेटाबेस का उपयोग कर सकते हैं एप्लिकेशन किसी भी कंप्यूटर और मेमोरी में चलाने में सक्षम होना चाहिए, मुझे नहीं पता कि SQLite में यह संभव है या नहीं। – Mixxiphoid

+0

@downvoter: समझाने की देखभाल? – Mixxiphoid

उत्तर

5

क्या तुमने कभी आइटम को पुन: व्यवस्थित करते हैं? यदि आप नहीं करते हैं, तो एक परिपत्र कतार काफी अच्छी तरह से काम करेगी।

सिस्टम। चयन। जेनरिक.क्यूयू एक है, मैंने बस दो बार चेक किया है। हमेशा पहले आइटम है

for (int i = 1; i < count; i++) 
    items[i-1] = items[i]; 
count--; 

क्योंकि list[0], आपको पहले आइटम को हटाने के लिए सब कुछ ले जाने के लिए है:

एक पंक्ति के लाभों पर विस्तार करने के लिए, इस RemoveAt कार्यान्वयन (मोटे तौर पर) है।

इसके विपरीत, एक कतार पहले आइटम को अलग से ट्रैक करती है। यह इस के लिए ऊपर दिए गए कोड में परिवर्तन:

head++ 
+0

नामस्थान के लिए धन्यवाद, मैं इसे देख लूंगा :)। – Mixxiphoid

+0

मैं वास्तव में वस्तुओं को किसी भी तरह से पुन: व्यवस्थित करता हूं। मैं अंत में सूची को उलट दूंगा, लेकिन इसे छोड़ना आसान है। – Mixxiphoid

+0

बहुत बहुत धन्यवाद! यह चाल है, मैं इस सवाल में अपना समाधान पोस्ट करूंगा। – Mixxiphoid

1

मैं बेहतर एक परिपत्र कतार लागू करने के लिए आप का सुझाव देगा। तो फिर तुम हर धक्का कतार के अंत करने के लिए int और आप अंतरिक्ष (निश्चित आकार के द्वारा निर्धारित) से बाहर चलाने के लिए जब तब प्रत्येक ऑपरेशन को पहले पॉप करने और नीचे धक्का देने की आवश्यकता होगी। O(1)

लाभ बनाम ऐरे यह है कि जब तक इसकी आवश्यकता न हो, तब तक आप अंतरिक्ष को पूर्ववत नहीं करेंगे। लेकिन, आखिरकार, इट्स को अच्छी तरह से स्टोर करने के लिए वास्तव में विचार करें। कोई फर्क नहीं पड़ता कि आप कौन से संचालन करेंगे, आपको हमेशा संख्याओं को संख्याओं के रूप में स्टोर करना चाहिए।

+0

क्या आप सुझाव देते हैं कि मुझे दो एरे रखना चाहिए, एक नंबर और दूसरे के लिए यदि उपयोगकर्ता अतिरिक्त जानकारी चाहता है? – Mixxiphoid

+0

नहीं। मैं सरणी के उपयोग का भी सुझाव नहीं दे रहा हूं। जो मैं आपको सोचने के लिए प्रोत्साहित करता हूं वह यह है कि यदि आपको वास्तव में अपने पूर्णांक के साथ अतिरिक्त जानकारी प्राप्त करने की आवश्यकता है। यदि ऐसा है, तो अच्छा, यदि नहीं, तो यदि आप कह सकते हैं कि संख्या के आधार पर जानकारी की गणना करें, तो बस नंबर को स्टोर करें। –

+0

संकेत के लिए धन्यवाद, मैं देखता हूं कि क्या संभव है। – Mixxiphoid

0

आप सरणी को पूर्ववत क्यों नहीं करते हैं, और दो पूर्णांक होते हैं, जो सरणी की शुरुआत और अंत का संकेत देते हैं। जाहिर है, वे दोनों 0 के बराबर शुरू हो जाएंगे। एक बार जब आप कमरे से बाहर निकल जाएंगे, तो आप बस चारों ओर लपेटना शुरू कर देंगे।

एक उदाहरण छद्म सहायक वर्ग:

class CircularArray 
{ 
    const int maxSize = 5000000; 
    private int[] arr = new int[maxSize]; 
    private int start = 0; 
    private int end = 0; 

    public void Add(int value) 
    { 
    int newEnd = (end + 1) % maxSize; 
    if (newEnd == start) 
     start = (start + 1) % maxSize; 
    end = newEnd; 
    arr[end] = value; 
    } 

    public int Get(int index) 
    { 
    int newIndex = (start + index) % maxSize; 
    return arr[newIndex]; 
    } 
} 
0

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

0

LinkedList<T> Class आपकी मदद कर सकता है? दोनों सिरों को हटाने और जोड़ने के लिए ओ (1) ऑपरेशन है, लेकिन पुनरावृत्ति ओ (एन) होगा, या यदि आपको एक्सेस करने पर ओ (1) की आवश्यकता है तो आप Dictionary या SortedDictionary का उपयोग कर सकते हैं एक और कस्टम-कार्यान्वयन QueueDictionary है, मैंने इसका इस्तेमाल किया जब मुझे ओ (1) ऑपरेशन को अंत में जोड़ने या हटाने (कतार/डेक्यू) और मूल्य तक पहुंचने पर दोनों की आवश्यकता होती है। QueueDictionary यहां: How would I implement a QueueDictionary, a combination of Queue and Dictionary in C#?

संबंधित मुद्दे