2016-03-24 23 views
12

मेरे पास ऑब्जेक्ट्स की एक सूची है। उन ऑब्जेक्ट्स में (दूसरों के बीच) एक निजी इंट ऐरे है (यदि यह मदद करता है, तो मैं इसे एक सूची में स्थानांतरित कर सकता हूं)। इस ऐरे के लिए एक सार्वजनिक गेटटर है। सभी Arrays एक ही आकार के हैं।मैं संग्रह में Arrays को कैसे व्यवस्थित कर सकता हूं?

मैं इस तरह उनके सरणी के आधार पर वस्तु क्रमबद्ध करना चाहते हैं:

Unsorted: 
{[0, 1, 4, 5], 
[0, 0, 2, 3], 
[0, 1, 1, 2]} 

Sorted: 
{[0, 0, 2, 3], 
[0, 1, 1, 2], 
[0, 1, 4, 5]} 

शब्दों में (यह lexicographical कहा जाता है):

  • प्रत्येक सरणी
  • अगर की पहली पूर्णांक तुलना वे बराबर हैं, प्रत्येक सरणी के अगले int (और इसी तरह) की तुलना करें
  • यदि वे तुलना के परिणाम के बराबर नहीं हैं तो अंतिम परिणाम है।

मैं उन्हें खोजने के लिए प्रबंधन करता हूं। एक सामान्य तुलनात्मक के साथ सरणी का केवल पहला तत्व है लेकिन मुझे नहीं पता कि उन्हें सभी के लिए कैसे खोजा जाए।

+0

स्पष्ट है: मेरे सरणी एक पूर्णांक [] है नहीं एक पूर्णांक [] – Maikefer

+10

यह वाकई दिलचस्प है लेकिन ... आप हमें नहीं दिखा तुम क्या कोशिश की है। कोड बनाने से आपको क्या रोक रहा है? –

+1

यदि सरणी निजी हैं, तो आप अपने ऑब्जेक्ट्स को सॉर्ट करने के लिए उनका उपयोग करने की अपेक्षा कैसे करते हैं? आप निजी संपत्तियों की तुलना नहीं कर सकते हैं। – Rainbolt

उत्तर

12

एक अच्छा जावा 8 समाधान

static final Comparator<CustomObject> COMPARATOR = (o1, o2) -> { 
    int[] arr1 = o1.getArray(); 
    int[] arr2 = o2.getArray(); 
    return IntStream.range(0, arr1.length) 
        .map(i -> Integer.compare(arr1[i], arr2[i])) 
        .filter(i -> i != 0) 
        .findFirst() 
        .orElse(0); 
}; 

फिर, एक List<CustomObject> को देखते हुए, आप कर सकते हैं

list.sort(COMPARATOR); 

(Comparator केवल एक ही लंबाई की सरणियों के लिए काम करता है। आप संशोधित करने के लिए चाहते हो सकता है यह)।

+1

हालांकि मुझे इस समाधान की _Java8_ness पसंद है, लेकिन मैं अपने चलने वाले समय के पहलुओं के बारे में विशेष रूप से उत्साहित नहीं हूं। 'मानचित्र' फ़ंक्शन को सभी पूर्णांक तुलना करने की आवश्यकता होगी, जबकि हम असमान मूल्यों की पहली जोड़ी ढूंढने के बाद बाकी को शॉर्ट-सर्किट कर सकते हैं। –

+7

@ केदारमहस्वाडे नहीं, यह शॉर्ट-सर्किट होगा, यह जांचने के लिए कि आप मुझ पर विश्वास नहीं करते हैं, आप 'peek' चिपक सकते हैं। –

+0

आप सही हैं, @ पॉल। मुझे और सोचना चाहिए था। –

8

मैं वस्तुओं का संग्रह (बेहतर सूची के कुछ प्रकार) है [...] अब मैं अपने सरणी के आधार पर वस्तु क्रमबद्ध करना चाहते हैं

यह बिल्कुल सार्थक होने के लिए , प्रश्न में Collection एक ऐसा होना चाहिए जो आदेश को संरक्षित करता है और आपको तत्वों को पुन: व्यवस्थित करने की अनुमति देता है। उच्च स्तरीय संग्रह इंटरफ़ेस के संदर्भ में, केवल List आवश्यक गुण हैं, इसलिए मान लें कि आपका Collection वास्तव में List है।

List को सॉर्ट करने का मानक तरीका दो Collections.sort() विधियों में से एक का उपयोग करना है। किसी को सूची तत्वों को Comparable लागू करने की आवश्यकता होती है, और दूसरा, अधिक सामान्य, आपको वस्तुओं के वांछित सापेक्ष क्रम को निर्धारित करने के लिए Comparator लागू करने के लिए एक ऑब्जेक्ट प्रदान करने की आवश्यकता होती है।

Arrays Comparable लागू नहीं करते हैं (जो कहने के बराबर है कि उनके पास "प्राकृतिक आदेश" नहीं है), लेकिन उनमें शामिल वस्तुओं की कक्षा को ऐसा करने के लिए बनाया जा सकता है। यह शायद बेहतर रूप है, हालांकि, एक अलग Comparator कक्षा लिखने के लिए जो आपके इच्छित आदेश लागू करता है, और उस वर्ग के उदाहरण का उपयोग करें।

6

मैं इसे सही ढंग से समझ रहा हूँ, तो निम्न स्पष्ट दृष्टिकोण से काम करना चाहिए:

public class SortArrays { 

    public static void main(String[] args) { 
     List<int[]> listOfArrays = new ArrayList<>(4); 
     listOfArrays.add(new int[]{0, 1, 4, 5}); 
     listOfArrays.add(new int[]{0, 0, 2, 3}); 
     listOfArrays.add(new int[]{0, 1, 1, 2}); 
     Collections.sort(listOfArrays, (o1, o2) -> { 
      for (int i = 0; i < o1.length; i++) { 
       if (o1[i] < o2[i]) 
        return -1; 
       if (o1[i] > o2[i]) 
        return 1; 
      } 
      return 0; 
     }); 
     listOfArrays.forEach(a -> System.out.println(Arrays.toString(a))); 
    } 
} 

यह पैदा करता है:

[0, 0, 2, 3] 
[0, 1, 1, 2] 
[0, 1, 4, 5] 

और वह है क्या आप उम्मीद करने लगते है।

+0

क्या होगा यदि ओ 2 ओ 1 से अधिक लंबा था? –

+1

परिणाम अपरिभाषित हैं;)। मैंने ओपी से पूछा था, और अगर इस मामले में कुछ निश्चित आवश्यक है तो इस जवाब को अपडेट कर देगा। –

+0

और मेरा मतलब छोटा था;) –

4

मान लीजिए कि आपकी कक्षा इस तरह कुछ दिखती है, और आप इसे संशोधित नहीं कर सकते हैं।

final class MyClass 
{ 
    private final int[] key; 

    MyClass(int[] key) 
    { 
    this.key = key.clone(); 
    } 

    public int[] getKey() 
    { 
    return key.clone(); 
    } 
} 

उसके बाद, आप Comparator इंटरफेस को लागू करने से MyClass की घटनाओं के लिए एक आदेश परिभाषित कर सकते हैं। अधिक सामान्य होने के लिए, मैं वास्तव में int[] के लिए एक तुलनित्र को लागू करने के लिए जा रहा हूँ:

final class IntArrayComparator 
    implements Comparator<int[]> 
{ 

    @Override 
    public int compare(int[] a, int[] b) 
    { 
    int n = Math.min(a.length, b.length); 
    for (int idx = 0; idx < n; ++idx) { 
     if (a[idx] != b[idx]) 
     return (a[idx] < b[idx]) ? -1 : +1; 
    } 
    return a.length - b.length; 
    } 
} 

इस नए तुलनित्र को देखते हुए, और अपने मौजूदा प्रकार, यह सॉर्ट करने के लिए आसान है:

final class Test 
{ 
    public static void main(String... arg) 
    { 
    /* Create your list somehow... */ 
    List<MyClass> list = new ArrayList<>(); 
    list.add(new MyClass(new int[]{0, 1, 4, 5})); 
    list.add(new MyClass(new int[]{0, 0, 2, 3})); 
    list.add(new MyClass(new int[]{0, 1, 1, 2})); 

    /* Now sort the list. */ 
    list.sort(Comparator.comparing(MyClass::getKey, new IntArrayComparator())); 

    /* Display the result... */ 
    list.stream().map(MyClass::getKey).map(Arrays::toString).forEach(System.out::println); 
    } 
} 

आप मिलना चाहिए उत्पादन: में प्रत्येक वस्तु से एक महत्वपूर्ण "निकालने" करने के लिए एक Function:

 
[0, 0, 2, 3] 
[0, 1, 1, 2] 
[0, 1, 4, 5] 

comparing() कारखाने विधि मैं उपयोग कर रहा हूँ दो तर्क लेता है सूची, और Comparator जो निकाली गई चाबियों की तुलना कर सकते हैं। यदि निकाली गई कुंजी में प्राकृतिक ऑर्डरिंग है, और Comparable लागू करता है (उदाहरण के लिए, यह String है), तो Comparator निर्दिष्ट करना आवश्यक नहीं है।

वैकल्पिक रूप से, आप MyClass संशोधित कर सकते हैं, तो आप यह Comparable को लागू करने और उसके compareTo() विधि के लिए int[] तुलना चलती, के रूप में अन्य उत्तर में दिखाया गया है द्वारा एक प्राकृतिक आदेश दे सकता है। फिर आप बिना तर्क के sort() विधि का उपयोग कर सकते हैं।

public class Foo { 

    private int[] values; 

    public Foo(int[] values) { 
     this.values = values; 
    } 
} 

वस्तुओं की एक सूची बनाने के लिए::

2

इस वस्तु पर विचार करें

ArrayList<Foo> foos = new ArrayList<>(); 
foos.add(new Foo(new int[] {0, 1, 4, 5})); 
foos.add(new Foo(new int[] {0, 0, 2, 3})); 
foos.add(new Foo(new int[] {0, 1, 1, 2})); 

अब हम वस्तुओं की हमारी सूची क्रमबद्ध करना चाहते हैं, तो पहली बात यह है कि हम क्या करना चाहिए हमारे वस्तु बनाने है Comparable लागू करें। आपको what the Comparable interface is और how to implement it और पढ़ना चाहिए।

public class Foo implements Comparable<Foo> { 
    ... 
} 

इस बिंदु पर अपने संकलक शिकायत करेगा कि आप इंटरफेस के लिए आवश्यक तरीकों के सभी लागू नहीं किया है। तो ऐसा करो।

public class Foo implements Comparable<Foo> { 
    ... 
    public int compareTo(Foo f) { 
     // Return a negative integer if this < f 
     // Return zero if this == f 
     // Return a positive integer if this > f 
    } 
} 

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

  • प्रत्येक सरणी की पहली संख्या की तुलना करें।
    • यदि वे बराबर हैं, तो प्रत्येक सरणी की अगली संख्या का उपयोग करके इस प्रक्रिया को दोहराएं।
    • अन्यथा, इस तुलना का परिणाम अंतिम परिणाम है।

आप वास्तव में अगर एक सरणी अन्य की तुलना में कम है कि क्या करना है निर्दिष्ट नहीं करते। मैं आपको वास्तविक एल्गोरिदम लिखना छोड़ दूंगा (हालांकि अन्य उत्तरों ने आपके लिए ऐसा किया है)।हालांकि, मैं इंगित करूंगा कि मान एक निजी क्षेत्र है, इसलिए आप उस क्षेत्र का उपयोग तुलना के लिए तब तक नहीं कर पाएंगे जबतक कि आप क्षेत्र के लिए गेटटर लागू नहीं करते हैं या इसे सार्वजनिक करते हैं।

public int[] getValues() { return values; } 
2

यदि आपका सरणी private है और आप प्रदान करने के लिए एक्सेसर विधि तो वर्ग के लिए Comparable को लागू करने और कोड के नीचे की तरह कुछ करना चाहते हैं।

यदि आपके पास कोई एक्सेसर विधि है तो इसे Comparator में करें।

यह कोड does not assume arrays to be of same size इसलिए यह विभिन्न आकार के सरणी के लिए काम करता है। कृपया अपनी जरूरत के हिसाब से बदलें।

पुनश्च - संकलित नहीं/

public int compareTo(Object o) { 
     CustomClass other = (CustomClass) o; 

     int i = 0; 
     while (i <= numbers.length && i <= other.numbers.length) { 
      if (numbers[i] < other.numbers[i]) 
       return -1; 
      else if (numbers[i] > other.numbers[i]) 
       return 1; 
      ++i; 
     } 

     if (numbers.length < other.numbers.length) 
      return -1; 
     else if (numbers.length > other.numbers.length) 
      return 1; 

     return 0; 
    } 
4

परीक्षण किया आदेश int की सरणियों की एक सूची सॉर्ट करने के लिए, आप एक समारोह है कि ints की एक सरणी के एक कोषगत तुलना करता है चाहता हूँ। यह आमतौर पर जावा में Comparator<int[]> के रूप में व्यक्त किया जाता है। इस तरह के फ़ंक्शन को लागू करने का सामान्य तरीका एक मेल नहीं मिला है, तब तक संबंधित मानों को बाएं से दाएं की तुलना करना है; वह मेलसमूह आदेश निर्धारित करता है। यदि किसी सरणी का अंत बिना किसी मिलान के पहुंचे, तो छोटे सरणी को आमतौर पर लंबे समय से कम माना जाता है। यदि लंबाई बराबर होती है, और सभी मान बराबर होते हैं, तो सरणी बराबर मानी जाती है।

अन्य उत्तर इस कार्य के लिए गुमनाम आंतरिक वर्ग या lambdas का इस्तेमाल किया है, लेकिन इस जैसी चीजों के लिए मैं एक साधारण विधि है कि सही "आकार", कि है, कि दो int[] तर्क लेता है और एक int जो रिटर्न पसंद करते हैं तुलना का परिणाम। यह इसे विधि संदर्भ के लक्ष्य के रूप में उपयोग करने में सक्षम बनाता है।

int arrayCompare(int[] a, int[] b) { 
    int len = Math.min(a.length, b.length); 
    for (int i = 0; i < len; i++) { 
     int c = Integer.compare(a[i], b[i]); 
     if (c != 0) { 
      return c; 
     } 
    } 
    return a.length - b.length; 
} 

नोट घटाव के बजाय Integer.compare() से सावधान उपयोग करते हैं, अतिप्रवाह के साथ संभावित समस्याओं से बचने।

List<int[]> arrays = Arrays.asList(
     new int[] { 0, 1, 4, 5 }, 
     new int[] { 0, 0, 2, 3 }, 
     new int[] { 0, 1, 1, 2 } 
    ); 

    arrays.sort(this::arrayCompare); 
    arrays.forEach(a -> System.out.println(Arrays.toString(a))); 

JDK 9 में, कोषगत सरणी तुलना कार्यों Arrays वर्ग के लिए जोड़ा गया है: प्रयोग इस प्रकार होगा। Arrays.compare(int[], int[]) देखें। अन्य आदिम प्रकारों और संदर्भ प्रकारों के लिए ओवरलोड भी हैं। int[] अधिभार arrayCompare समारोह मैंने ऊपर लिखा है की जगह है, तो आप के रूप में इस तरह कॉल पुनर्लेखन कर सकते हैं:

arrays.sort(Arrays::compare); 

Arrays कक्षा में तुलना कार्यों का लाभ यह है कि वे JVM, द्वारा विशेष रूप से संभाला जा सकता है जो उदाहरण के लिए, सरणी तुलना को तेज करने के लिए वेक्टर निर्देशों का उपयोग कर सकते हैं।

अपने विशिष्ट समस्या के लिए, यह आप की तरह int[] की एक सूची की जरूरत नहीं है लगता है, लेकिन आप प्रकार MyObject की वस्तुओं की एक सूची है कि एक int[] कि आप तरह कुंजी के रूप में उपयोग करना चाहते हैं। मान लें कि सरणी प्राप्त करने का तरीका विधि getArray() पर कॉल करके है। इस प्रकार आप सूची को सॉर्ट कर सकते हैं:

myObjects.sort(Comparator.comparing(MyObject::getArray, Arrays::compare)); 
+0

क्या जेडीके 9 को लिक्सिकोग्राफिक रूप से सूचीबद्ध सूची के लिए समर्थन है? यदि हां, तो क्या आप एक तुलनात्मक में यह कहने के लिए पास कर सकते हैं कि अलग-अलग तत्वों की तुलना कैसे की जानी चाहिए? –

+0

@ पॉलबोडिंगटन जेडीके में नहीं। लेकिन अमरूद में 'ऑर्डरिंग। लक्सिफोग्राफिकल()' है जो यह करता है। –

+0

उत्तर के लिए धन्यवाद। –

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

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