वस्तुओं को फेरने का कुशल तरीका


20

मैं कुछ प्रश्नोत्तरी सॉफ्टवेयर के लिए एक कार्यक्रम लिख रहा हूं। मेरे पास एक प्रश्न वर्ग है जिसमें प्रश्न, उत्तर, विकल्प, अंक और नकारात्मक अंक के लिए ArrayLists हैं। कुछ इस तरह:

class question
{
    private ArrayList<Integer> index_list;
    private ArrayList<String> question_list;        
    private ArrayList<String> answer_list;      
    private ArrayList<String> opt1_list;        
    private ArrayList<String> opt2_list;    
}

मैं सभी प्रश्नों में फेरबदल करना चाहता हूं, लेकिन सवालों के फेरबदल के लिए, सभी वस्तुओं को फेरबदल करने की आवश्यकता है। मैं इस तरह से इस समस्या से संपर्क किया होगा:

सबसे पहले, मैंने इस डिज़ाइन का उपयोग नहीं किया होगा और स्ट्रिंग ArrayList<String>वेरिएबल का उपयोग नहीं किया था उदाहरण के चर के रूप में, और फिर Collections.shuffleवस्तुओं को फेरबदल करने के लिए विधि का उपयोग किया होगा । लेकिन मेरी टीम इस डिजाइन पर जोर देती है।

अब, प्रश्न वर्ग में ArrayLists बढ़ रहा है, क्योंकि प्रश्नों की प्रविष्टि की जाती है। अब सवालों से कैसे किनारा करें?


30
मुझे निरपेक्षता में बात करने से नफरत है, लेकिन अगर आपकी टीम इस डिजाइन पर जोर देती है, तो वे गलत हैं। उन्हें बताओ! उन्हें बताएं कि मैंने ऐसा कहा (और मैंने इसे इंटरनेट पर लिखा है, इसलिए मुझे सही होना है)।
जोकिम सॉयर

10
हां, उन्हें बताएं कि यहां बहुत सारे लोग हैं जो आपको बता रहे हैं कि इस तरह की डिजाइन एक विशिष्ट शुरुआती गलती है।
डॉक ब्राउन

6
जिज्ञासा से बाहर: आपकी टीम इस डिजाइन में क्या फायदे देखती है?
जोआचिम सॉयर

9
जावा नामकरण सम्मेलनों में वर्ग के नाम के लिए CamelCase और चर नामों के लिए CamelCase हैं।
ट्यूलेंस कोर्डोवा

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

जवाबों:


95

आपकी टीम एक आम समस्या से ग्रस्त है: वस्तु इनकार

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

इसके बारे में जाने का गलत तरीका है, और यह आपको बहुत कुछ करने की कोशिश करता है ! सॉर्टिंग (और फेरबदल) समानांतर सरणियाँ (या सूचियाँ) बुरा व्यवसाय है और इसके लिए कोई सामान्य एपीआई नहीं है, बस इसलिए कि आप आमतौर पर इससे बचना चाहते हैं

मेरा सुझाव है कि आप अपना कोड इस तरह से पुनर्गठन करेंगे:

class Question
{
    private Integer index;
    private String question;        
    private String answer;      
    private String opt1;        
    private String opt2;    
}

// somewhere else
List<Question> questionList = new ArrayList<Question>();

इस तरह, आपके प्रश्न का फेरबदल तुच्छ हो जाता है (उपयोग करते हुए Collections.shuffle()):

Collections.shuffle(questionList);

39
यह भी वस्तु इनकार नहीं है यह डेटा संरचना इनकार
jk है।

22

तुम नहीं। आप अनुक्रमित और फेरबदल की एक और सूची / कतार बनाते हैं। फिर आप उन अनुक्रमणिकाओं को पुन: व्यवस्थित करते हैं जो आपके अन्य संग्रह के "फेरबदल" क्रम को चलाते हैं।

अलग-अलग चीजों के साथ अपने परिदृश्य के बाहर भी, अलग-अलग ऑर्डरिंग संग्रह कई लाभ प्रदान करता है (समानता, गति जब मूल संग्रह को फिर से भरना महंगा है, आदि)।


10
मैं इसे वोट करने के लिए अनिच्छुक हूं: यह अगला सबसे अच्छा समाधान है अगर यह डिजाइन वास्तव में तय हो गया है, लेकिन इस डिजाइन पर जोर देना इतना गलत है, कि मैं इसके बारे में कोई सुझाव नहीं देना चाहूंगा। (meh, वैसे भी अपवित्र ;-))
जोकिम सॉयर

3
@joachimSauer - जब मैं सहमत हूं, तो बहुत सारे अन्य (कम आक्रामक) परिदृश्य हैं जहां मूल संग्रह को स्थिर रहना चाहिए, जबकि उनके माध्यम से रास्ता अलग-अलग होना चाहिए।
तेलस्तीन

4
हाँ मैं जानता हूँ। और सूचकांकों का संग्रह फेरबदल करना उन स्थितियों के लिए सही दृष्टिकोण है। मेरा एकमात्र डर यह है कि ओपीएस टीम सिर्फ यह लेगी और "अच्छा पर्याप्त" कहेगी, बिना उनके डिजाइन को फिर से देखे।
जोआचिम सॉयर

1
यह उत्तर विशेष रूप से उस मामले के लिए मूल्यवान है, जहां किसी को अंतर्निहित संग्रह वर्ग या संरचना को संशोधित / पुन: व्यवस्थित करने की स्वतंत्रता नहीं है, जैसे कि किसी को ओएस बनाए रखा संग्रह के लिए एपीआई के साथ करना पड़ता है। सूचकांक में फेरबदल एक महान अंतर्दृष्टि है और खुद भी खड़ा है, भले ही यह अंतर्निहित डिजाइन को फिर से परिभाषित करने के रूप में एक अंतर्दृष्टि नहीं है।
हार्डमैथ

@ जोकिम सौर: वास्तव में सूचकांकों को फेरबदल करना समस्या के लिए सबसे अच्छा समाधान नहीं है जैसा कि कहा गया है। एक विकल्प के लिए मेरा जवाब देखें।
माइकल बोर्गवर्ड

16

मैं अन्य उत्तरों से सहमत हूं कि सही समाधान एक उचित ऑब्जेक्ट मॉडल का उपयोग करना है।

हालाँकि, वास्तव में कई सूचियों को समान तरीके से फेरबदल करना काफी आसान है:

Random rnd = new Random();
long seed = rnd.nextLong();

rnd.setSeed(seed);
Collections.shuffle(index_list, rnd);
rnd.setSeed(seed);
Collections.shuffle(question_list, rnd);
rnd.setSeed(seed);
Collections.shuffle(answer_list, rnd);
...

यह ... यह करने के लिए एक साफ तरीका है! अब, "सॉर्टिंग" मामले के लिए, हमें बस एक ऐसा बीज खोजने की जरूरत है, जो इस तरह से लागू होने पर हल की गई सूची बनाता है और फिर हम इस बीज के साथ सभी सूचियों को फेरबदल करते हैं!
जोआचिम सॉयर

1
@JoachimSauer: ठीक है, छँटाई समस्या का हिस्सा नहीं थी। हालांकि यह एक दिलचस्प सवाल है कि क्या किसी दिए गए आरएनजी के लिए इस तरह के बीज को खोजने का कोई व्यवस्थित तरीका है।
माइकल बोर्गवर्ड

2
@MichaelBorgwardt एक बार जब आप 17 से अधिक प्रश्न प्राप्त कर लेते हैं, तो आप 48 बिट्स में संभव फेरबदल की मात्रा को व्यक्त नहीं कर सकते हैं java रैंडम का उपयोग करता है (log_2 (17!) = 48.33)
शाफ़्ट सनकी 12

@ratchetfreak: मेरे लिए एक वास्तविक समस्या की तरह नहीं है। और यह सुरक्षित है अगर आप चाहिए के बजाय SecureRandom का उपयोग करने के लिए।
माइकल बोर्गवर्ड

4
@ टेलस्टाइन: इंडेक्स की सूची IMO अप्रत्यक्ष की एक परत है जो आपके समाधान को वैचारिक रूप से अधिक जटिल बनाती है, और क्या यह अधिक या कम प्रदर्शनकर्ता पर निर्भर करता है कि फेरबदल के बाद सूची कितनी बार एक्सेस की जाती है। लेकिन मानव द्वारा उत्तर दिए जाने वाले क्विज़ के लिए प्रदर्शन के अंतर को महत्वहीन रूप दिया जाएगा।
माइकल बोर्गवर्ड

3

एक वर्ग बनाएँ Question2:

class Question2
{
    public Integer index_list;
    public String question_list;        
    public String answer_list;      
    public String opt1_list;        
    public String opt2_list;    
}

फिर एक समारोह एक मानचित्रण बनाने questionके लिए ArrayList<Question2>, का उपयोग करें Collection.Shuffleकि परिणाम के लिए, और मानचित्रण के लिए एक दूसरे समारोह बनाने ArrayList<Question2>के लिए वापस question

बाद में, अपनी टीम के पास जाएं और उन्हें समझाने की कोशिश करें कि ArrayList<Question2>इसके बजाय questionउनके कोड का उपयोग करने से बहुत सुधार होगा, क्योंकि यह उन्हें बहुत सारे अनावश्यक रूपांतरणों से बचाएगा।


1
यह एक अच्छा विचार है, लेकिन केवल एक प्राथमिकता के बाद ही डिजाइन को बदलने के प्रयास विफल हो गए हैं।
सेबेस्टियन रेडल

@ एसबेस्टियनरेडल: कभी-कभी कोड में समाधान दिखाते समय बेहतर डिजाइन के लोगों को समझाना आसान होता है।
डॉक ब्राउन

1

मेरा मूल भोला और गलत उत्तर:

बस प्रत्येक सूची के लिए लूप के लिए आइटम में कम से कम (कम से कम) nरैंडम नंबर और इंटरचेंज आइटम बनाएं ।ni

छद्म कोड में:

for (in i = 0; i < question_list.length(); i++) {
  int random = randomNumber(0, questions_list.length()-1);
  question_list.switchItems(i, random);
  answer_list.switchItems(i, random);
  opt1_list.switchItems(i, random);
  opt2_list.switchItems(i, random);

}

अपडेट करें:

कोडिंग हॉरर लेख को इंगित करने के लिए the_lotus के लिए धन्यवाद। मैं अब बहुत चालाक महसूस करता हूँ :-) वैसे भी जेफ एटवुड को यह भी पता चलता है कि फिशर-येट्स एल्गोरिथ्म का उपयोग करके इसे सही तरीके से कैसे किया जाता है :

for (int i = question_list.Length - 1; i > 0; i--){
  int n = rand.Next(i + 1); //assuming rand.Next(x) returns values between 0 and x-1
  question_list.switchItems(i, n);
  answer_list.switchItems(i, n);
  opt1_list.switchItems(i, n);
  opt2_list.switchItems(i, n);
}

यहां मुख्य अंतर यह है कि प्रत्येक तत्व को केवल एक बार स्वैप किया जाता है।

और जबकि अन्य उत्तर सही ढंग से समझाते हैं कि आपका ऑब्जेक्ट मॉडल त्रुटिपूर्ण है, आप इसे बदलने के लिए पॉज़िटिवोन में नहीं हो सकते हैं। तो फिशर-येट्स एल्गोरिथ्म आपके डेटा मॉडल को बदलने के बिना आपकी समस्या को हल करेगा।


हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.