2011-10-24 9 views
6

यदि मेरे पास गुवा मल्टीमैप है, तो मैं दिए गए कुंजी के मानों की संख्या के आधार पर प्रविष्टियों को कैसे क्रमबद्ध करूं?मूल्यों की संख्या के आधार पर गुवा मल्टीमैप को क्रमबद्ध करें

उदाहरण के लिए:

Multimap<String, String> multiMap = ArrayListMultimap.create(); 
multiMap.put("foo", "1"); 
multiMap.put("bar", "2"); 
multiMap.put("bar", "3"); 
multiMap.put("bar", "99"); 

को देखते हुए यह, जब मल्टीमैप से अधिक पुनरावृत्ति, मैं कैसे मिलेगा "बार" प्रविष्टियों पहले आने के लिए (के बाद से "बार" 3 मूल्यों बनाम केवल 1 "foo" है)?

उत्तर

13

एक सूची में प्रविष्टियों निकालें, तो सूची क्रमबद्ध करें:

List<Map.Entry<String, String>> entries = new ArrayList<Map.Entry<String, String>>(map.entries()); 
Collections.sort(entries, new Comparator<Map.Entry<String, String>>() { 
    @Override 
    public int compare(Map.Entry<String, String> e1, Map.Entry<String, String> e2) { 
     return Ints.compare(map.get(e2.getKey()).size(), map.get(e1.getKey()).size()); 
    } 
}); 

तब प्रविष्टियों से अधिक पुनरावृति।

संपादित करें:

List<Map.Entry<String, Collection<String>>> entries = 
    new ArrayList<Map.Entry<String, Collection<String>>>(map.asMap().entrySet()); 
Collections.sort(entries, new Comparator<Map.Entry<String, Collection<String>>>() { 
    @Override 
    public int compare(Map.Entry<String, Collection<String>> e1, 
         Map.Entry<String, Collection<String>> e2) { 
     return Ints.compare(e2.getValue().size(), e1.getValue().size()); 
    } 
}); 

// and now iterate 
for (Map.Entry<String, Collection<String>> entry : entries) { 
    System.out.println("Key = " + entry.getKey()); 
    for (String value : entry.getValue()) { 
     System.out.println(" Value = " + value); 
    } 
} 
+0

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

+0

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

+0

क्षमा करें मेरा मूल प्रश्न बिल्कुल स्पष्ट नहीं था। मैं मूल मल्टीमैप पर पुन: प्रयास करने में सक्षम होना चाहता हूं, लेकिन पहले सबसे ज्यादा गिनती प्रविष्टियां प्राप्त करें। इसके अलावा, एक TreeMultimap ने चाबियाँ (और मान) को क्रमबद्ध किया है, इसलिए यह कहना आवश्यक नहीं है कि मल्टीमैप का आदेश नहीं दिया गया है। –

8

मैं मल्टीमैप के keys Multiset प्रविष्टियों का उपयोग करना चाहते हैं,:

यदि आप चाहते हैं आंतरिक नक्शा (Entry<String, Collection<String>>) की प्रविष्टियों से अधिक तथ्य पुनरावृति में है, तो निम्न कार्य करें उन्हें अवरोही आवृत्ति के अनुसार क्रमबद्ध करें (issue 356 में वर्णित कार्यक्षमता को गुवा में जोड़ा जाने वाला कार्यक्षमता आसान हो जाएगा), और क्रमबद्ध कुंजी को पुन: स्थापित करके एक नया मल्टीमैप बनाएं, मूल मल्टीमैप से मूल्य प्राप्त करना:

/** 
* @return a {@link Multimap} whose entries are sorted by descending frequency 
*/ 
public Multimap<String, String> sortedByDescendingFrequency(Multimap<String, String> multimap) { 
    // ImmutableMultimap.Builder preserves key/value order 
    ImmutableMultimap.Builder<String, String> result = ImmutableMultimap.builder(); 
    for (Multiset.Entry<String> entry : DESCENDING_COUNT_ORDERING.sortedCopy(multimap.keys().entrySet())) { 
     result.putAll(entry.getElement(), multimap.get(entry.getElement())); 
    } 
    return result.build(); 
} 

/** 
* An {@link Ordering} that orders {@link Multiset.Entry Multiset entries} by ascending count. 
*/ 
private static final Ordering<Multiset.Entry<?>> ASCENDING_COUNT_ORDERING = new Ordering<Multiset.Entry<?>>() { 
    @Override 
    public int compare(Multiset.Entry<?> left, Multiset.Entry<?> right) { 
     return Ints.compare(left.getCount(), right.getCount()); 
    } 
}; 

/** 
* An {@link Ordering} that orders {@link Multiset.Entry Multiset entries} by descending count. 
*/ 
private static final Ordering<Multiset.Entry<?>> DESCENDING_COUNT_ORDERING = ASCENDING_COUNT_ORDERING.reverse(); 

संपादित करें: इस काम नहीं करता है कुछ प्रविष्टियों (मेरी टिप्पणी देखें)

एक और दृष्टिकोण, पर Multimaps 'चाबियाँ मल्टीसेट आधार पर एक आदेश का उपयोग कर, और ImmutableMultimap.Builder.orderKeysBy() एक ही आवृत्ति है:

/** 
* @return a {@link Multimap} whose entries are sorted by descending frequency 
*/ 
public Multimap<String, String> sortedByDescendingFrequency(Multimap<String, String> multimap) { 
    return ImmutableMultimap.<String, String>builder() 
      .orderKeysBy(descendingCountOrdering(multimap.keys())) 
      .putAll(multimap) 
      .build(); 
} 

private static Ordering<String> descendingCountOrdering(final Multiset<String> multiset) { 
    return new Ordering<String>() { 
     @Override 
     public int compare(String left, String right) { 
      return Ints.compare(multiset.count(left), multiset.count(right)); 
     } 
    }; 
} 

दूसरा दृष्टिकोण छोटा है, लेकिन मुझे यह तथ्य पसंद नहीं है कि ऑर्डरिंग में राज्य है (यह चाबियों की तुलना करने के लिए मल्टीमैप की कुंजी मल्टीसेट पर निर्भर करता है)।

+3

धन्यवाद! पहला दृष्टिकोण बहुत अच्छा काम करता था, ठीक वही था जो मैं चाहता था। दूसरे दृष्टिकोण के साथ कुछ गड़बड़ है, हालांकि (अभी तक यह पता लगाने के लिए इसे डिबग नहीं किया गया है ... लेकिन मेरे टेस्ट डेटा के साथ मैं एक इनपुट मल्टीमैप से शुरू करता हूं जिसका asMap() आकार 432 है, लेकिन आउटपुट मल्टीमैप के asMap() आकार केवल 21. –

+0

यह वास्तव में अजीब है। जब मैं कुछ समय पा सकता हूं तो मैं इसका परीक्षण करने जा रहा हूं। मैंने गलती की हो सकती है। आप सुनिश्चित हैं कि आप inputMultimap.asMap() के साथ inputMultimap.size() की तुलना नहीं कर रहे हैं। आकार()? –

+0

सही, मैं दोनों पर asMap() आकार() की तुलना कर रहा था। –

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