জাভা অ্যারেলিস্ট - যদি দুটি তালিকা সমান হয় তবে অর্ডার বিবেচনা না করে আমি কীভাবে বলতে পারি?


133

আমার দুটি ArrayListধরণের টাইপ রয়েছে Answer(স্ব-তৈরি ক্লাস)।

আমি দুটি তালিকার তুলনা করতে চাই যাতে সেগুলিতে একই বিষয়বস্তু রয়েছে তবে অর্ডার না করেই।

উদাহরণ:

//These should be equal.
ArrayList<String> listA = {"a", "b", "c"}
ArrayList<String> listB = {"b", "c", "a"}

List.equalsদুটি তালিকা একই আকারের, সামগ্রী এবং উপাদানগুলির ক্রম সমেত বলে সমীক্ষা করে। আমি একই জিনিস চাই, কিন্তু অর্ডার ব্যাপার না করে।

এটি করার কোন সহজ পথ আছে কি? বা লুপের জন্য আমার নেস্টেড করার দরকার আছে এবং উভয় তালিকার প্রতিটি সূচকে ম্যানুয়ালি পরীক্ষা করতে হবে?

দ্রষ্টব্য: আমি এগুলিকে ArrayListঅন্য ধরণের তালিকায় পরিবর্তন করতে পারি না , তাদের এটি থাকা দরকার।


4
: এই প্রশ্নের জন্য উত্তর দেখার stackoverflow.com/a/1075699/1133011
ডেভিড Kroukamp

জাভাতে লিস্টকন্টিনস সব (তালিকা) দেখুন
সাহিল জৈন

উত্তর:


130

আপনি উভয় তালিকাগুলি ব্যবহার করে বাছাই করতে পারেন Collections.sort()এবং তারপরে সমান পদ্ধতিটি ব্যবহার করতে পারেন। একটি অল্পতর ভাল সমাধান হ'ল প্রথমে পরীক্ষা করার জন্য তারা অর্ডার দেওয়ার আগে একই দৈর্ঘ্য কিনা, যদি তা না হয় তবে তারা সমান হয় না, বাছাই করুন, তারপরে সমান ব্যবহার করুন। উদাহরণস্বরূপ আপনার যদি স্ট্রিংয়ের দুটি তালিকা থাকে তবে এটি এমন হবে:

public  boolean equalLists(List<String> one, List<String> two){     
    if (one == null && two == null){
        return true;
    }

    if((one == null && two != null) 
      || one != null && two == null
      || one.size() != two.size()){
        return false;
    }

    //to avoid messing the order of the lists we will use a copy
    //as noted in comments by A. R. S.
    one = new ArrayList<String>(one); 
    two = new ArrayList<String>(two);   

    Collections.sort(one);
    Collections.sort(two);      
    return one.equals(two);
}

20
কেবল মনে রাখবেন মূল তালিকার ক্রমটি (যেমনটি Collections.sortহয়) না ধ্বংস করুন - অর্থাত্ একটি অনুলিপি পাস করুন।
আর্শাজি

@ আরএস হ্যাঁ এটি একটি সুনির্দিষ্ট পার্শ্ব প্রতিক্রিয়া, তবে এটি যদি তাদের বিশেষ ক্ষেত্রে গুরুত্বপূর্ণ হয়।
জ্যাকব শোয়েন

3
one = new ArrayList<String>(one); two = new ArrayList<String>(two);যুক্তি নষ্ট না করার জন্য আপনি কেবল যুক্ত করতে পারেন ।
আর্শাজি

@ জেসকোইন সংগ্রহের চেষ্টা করছেন sSort () আমাকে এই ত্রুটিটি দিচ্ছে: বাউন্ডম মেলে না: জেনেরিক পদ্ধতির সাজানোর (তালিকা <T>) সংগ্রহের ধরণের আর্গুমেন্টের জন্য প্রযোজ্য নয় (অ্যারেলিস্ট <উত্তর>)। ইনফেরার্ড টাইপ উত্তর সীমান্ত প্যারামিটারের জন্য বৈধ বিকল্প নয় <টি তুলনীয় <টি প্রসারিত করে? সুপার টি >>
iaacp

3
ফাংশনের অভ্যন্তরে দ্বিতীয় "যদি" বিবৃতিটি সরল করা যেতে পারে if(one == null || two == null || one.size() != two.size()){ return false; }কারণ আপনি ইতিমধ্যে যাচ্ছেন একজন এবং দু'জনই নাল কিনা তা পরীক্ষা করছেন
হুগো

151

সম্ভবত যে কোনও তালিকার সহজতম উপায় হ'ল :

listA.containsAll(listB) && listB.containsAll(listA)

5
কোথায় যে মজা. সমস্ত গুরুত্বের সাথে যদিও এটি সম্ভবত আরও ভাল সমাধান।
জ্যাকব শোয়েন

67
একই বিষয়বস্তু আছে কিনা তা বিবেচনা করা হয় [a, b, c]এবং তা নির্ভর করে [c, b, a, b]। এই উত্তরটি বলবে যে তারা করে, তবে এটি হতে পারে যে ওপি-র জন্য তারা না করে (যেহেতু একটিতে সদৃশ রয়েছে এবং অন্যটিতে তা নেই)। দক্ষতা সমস্যা কিছুই বলতে।
ysavit

4
মন্তব্যের ভিত্তিতে বর্ধিতকরণ - System.out.println (((l1.size () == l2.size ())) && l2.containsAll (l1) && l1.containsAll (l2)));
Nrj

8
@ এনআরজে, [1,2,2] এবং [2,1,1] সম্পর্কে কী?
রোমানিয়া_আজ্ঞানী 18

3
এই পদ্ধতির হে (এন ^ 2) এর জটিলতা রয়েছে। বিপরীত ক্রমে দুটি তালিকা বিবেচনা করুন, যেমন: [1,2,3] এবং [3,2,1]। প্রথম উপাদানটির জন্য এটি এন উপাদানগুলিকে স্ক্যান করতে হবে, দ্বিতীয় এন -1 উপাদানগুলির জন্য এবং আরও অনেক কিছু। সুতরাং জটিলতা অর্ডার n ^ 2 হবে। আমি মনে করি ভাল উপায় বাছাই করা এবং তারপরে সমান ব্যবহার করা হবে। এটিতে ও (এন * লগ (এন)) এর জটিলতা থাকবে
পুণিত

90

আবারও উদ্ধারে অ্যাপাচি কমন্স সংগ্রহসমূহ:

List<String> listA = Arrays.asList("a", "b", "b", "c");
List<String> listB = Arrays.asList("b", "c", "a", "b");
System.out.println(CollectionUtils.isEqualCollection(listA, listB)); // true

 

List<String> listC = Arrays.asList("a", "b", "c");
List<String> listD = Arrays.asList("a", "b", "c", "c");
System.out.println(CollectionUtils.isEqualCollection(listC, listD)); // false

দস্তাবেজ:

org.apache.commons.collections4.CollectionUtils

public static boolean isEqualCollection(java.util.Collection a,
                                        java.util.Collection b)

trueপ্রদত্ত Collectionগুলি একই কার্ডিনালিটির সাথে হুবহু একই উপাদান উপস্থিত থাকলে ফেরত দেয় ।

অর্থাৎ এর cardinality iff মধ্যে একটি এর cardinality সমান মধ্যে প্রতিটি উপাদান জন্য, মধ্যে একটি বা বো

পরামিতি:

  • a - প্রথম সংগ্রহ, হবে না null
  • b - দ্বিতীয় সংগ্রহ, হতে হবে না null

রিটার্নস: trueযদি সংগ্রহগুলিতে একই কার্ডিনালিটির সাথে একই উপাদান থাকে।


বাস্তবায়ন কমবেশি ডিডিজেড এর উত্তরের সাথে মিল বলে মনে হচ্ছে।
ব্যবহারকারী 227353

ঠিক আছে ... তবে যদি উত্তর হয় তবে দোষীদের ধরে রাখা (যে উপাদানগুলি দুটি তালিকার পক্ষে সাধারণ নয়) তার falseকী হবে ? আমার উত্তর দেখুন।
মাইকে রডেন্ট

implementation 'org.apache.commons:commons-collections4:4.3'আমাকে ত্রুটির Caused by: com.android.builder.dexing.DexArchiveBuilderException: Failed to process পথে ফেলেছে ।
অ্যালিটন অলিভিরা

13
// helper class, so we don't have to do a whole lot of autoboxing
private static class Count {
    public int count = 0;
}

public boolean haveSameElements(final List<String> list1, final List<String> list2) {
    // (list1, list1) is always true
    if (list1 == list2) return true;

    // If either list is null, or the lengths are not equal, they can't possibly match 
    if (list1 == null || list2 == null || list1.size() != list2.size())
        return false;

    // (switch the two checks above if (null, null) should return false)

    Map<String, Count> counts = new HashMap<>();

    // Count the items in list1
    for (String item : list1) {
        if (!counts.containsKey(item)) counts.put(item, new Count());
        counts.get(item).count += 1;
    }

    // Subtract the count of items in list2
    for (String item : list2) {
        // If the map doesn't contain the item here, then this item wasn't in list1
        if (!counts.containsKey(item)) return false;
        counts.get(item).count -= 1;
    }

    // If any count is nonzero at this point, then the two lists don't match
    for (Map.Entry<String, Count> entry : counts.entrySet()) {
        if (entry.getValue().count != 0) return false;
    }

    return true;
}

বাহ, অন্যান্য সমস্ত সমাধানের চেয়ে দ্রুত এই পারফরম্যান্সটি পেয়ে সত্যিই অবাক হয়েছিল। এবং এটি প্রারম্ভিক আউট সমর্থন করে।
দিদিজেড

এটি দ্বিতীয় লুপের শর্ট সার্কিটও হতে পারে, যদি countনেতিবাচক হয়ে যায়, লুপের বডিটি সরল করে তোলে if(!counts.containsKey(item) || --counts.get(item).count < 0) return false;তৃতীয় লুপটি সরল করা যেতে পারেfor(Count c: counts.values()) if(c.count != 0) return false;
হলগার

@ হোলজার আমি প্রথমটির মতো কিছু বিবেচনা করছিলাম (শূন্যের সাথে আঘাত করলে গণনা অপসারণ করা, যার ফলস্বরূপ একই প্রভাব থাকবে তবে শেষের দিকে চেকগুলি " countsখালি কিনা" ফেরত রূপান্তরিত করবে ), কিন্তু অস্পষ্ট করতে চাইনি মূল বক্তব্য: মানচিত্রটি ব্যবহার করা মূলত এটিকে একটি ও (এন + এম) সমস্যায় পরিণত করে এবং এটি সম্ভবত আপনি সবচেয়ে বড় উত্সাহ পাবেন।
সিএইচও

@ সি হাও, হ্যাঁ, পূর্বেরগুলির চেয়ে ভাল সময়ের জটিলতার সাথে সমাধানের দিকে ইশারা করার জন্য আপনি ক্রেডিট প্রাপ্য। আমি এটি সম্পর্কে ভাবতে পেরেছি, কারণ পুনরাবৃত্তি সম্পর্কে সাম্প্রতিক একই প্রশ্ন রয়েছে। যেহেতু আমাদের কাছে এখন জাভা 8 রয়েছে, তাই এটি পুনর্বিবেচনা করার মতো ছিল। সংখ্যাটি নেতিবাচক হয়ে উঠলে আপনি যদি দ্বিতীয় লুপে শর্ট সার্কিট করেন তবে তৃতীয় লুপটি অচল হয়ে যায়। তদুপরি, বক্সিং এড়িয়ে চলা একটি দ্বি-তরোয়াল তরোয়াল হতে পারে, নতুন সহ Map.merge, বাক্সযুক্ত পূর্ণসংখ্যা ব্যবহার করা বেশিরভাগ ক্ষেত্রে ব্যবহারের ক্ষেত্রে সহজ এবং আরও কার্যকর হতে পারে। এই
হোলার

10

আমি এই উত্তরগুলি একটি কৌশল মিস্ বলব।

ব্লচ তার প্রয়োজনীয়, দুর্দান্ত, সংক্ষিপ্ত কার্যকর জাভাতে বলেছেন, আইটেম 47-এ শিরোনাম "লাইব্রেরিগুলি জেনে নিন এবং ব্যবহার করুন", "সংক্ষেপে জানাতে, চাকাটি পুনরায় উদ্ভাবন করবেন না" title এবং না কেন তিনি বেশ কয়েকটি স্পষ্ট কারণ দিয়েছেন।

এখানে কয়েকটি উত্তর রয়েছে যা CollectionUtilsঅ্যাপাচি কমন্স সংগ্রহের পাঠাগার থেকে পদ্ধতিগুলি নির্দেশ করে তবে এই প্রশ্নের উত্তর দেওয়ার সবচেয়ে সুন্দর, মার্জিত উপায় কেউ খুঁজে পায়নি :

Collection<Object> culprits = CollectionUtils.disjunction( list1, list2 );
if( ! culprits.isEmpty() ){
  // ... do something with the culprits, i.e. elements which are not common

}

দোষী : অর্থাৎ যে উপাদানগুলি উভয়ের পক্ষে সাধারণ নয় Lists। কোন অপরাধী কোনটির সাথে সম্পর্কিত list1এবং কোনটি list2অপেক্ষাকৃত সহজবোধ্য ব্যবহার CollectionUtils.intersection( list1, culprits )এবং তা নির্ধারণ করা CollectionUtils.intersection( list2, culprits )
তবে এটি a "ক", "ক", "বি"} এর disjunctionসাথে a "ক", "বি", "বি" cases এর মতো ক্ষেত্রে বিচ্ছিন্ন হয়ে পড়েছে ... এটি বাদে সফ্টওয়্যারটির ব্যর্থতা নয়, তবে পছন্দসই কাজের সূক্ষ্মতা / অস্পষ্টতার প্রকৃতির সহজাত।

অ্যাপাচি ইঞ্জিনিয়ারদের দ্বারা উত্পাদিত হিসাবে আপনি এই জাতীয় কাজের জন্য সর্বদা উত্স কোড (l। 287) পরীক্ষা করতে পারেন । তাদের কোড ব্যবহার করার একটি সুবিধা হ'ল এটি অনেকগুলি প্রান্তের কেস এবং প্রত্যাশিত এবং মোকাবেলা করা সহ পুরোপুরি বিচার ও পরীক্ষা করা হবে। আপনি যদি প্রয়োজন হয় তবে এই কোডটি আপনার হৃদয়ের সামগ্রীতে অনুলিপি করতে পারেন এবং কপি করতে পারেন।


এনবি আমি প্রথমে হতাশ হয়ে পড়েছিলাম যে কোনও CollectionUtilsপদ্ধতিরই আপনাকে নিজের চাপ প্রয়োগ করতে সক্ষম করার জন্য একটি ওভারলোডেড সংস্করণ সরবরাহ করে না Comparator(যাতে আপনি নিজের equalsউদ্দেশ্য অনুসারে পুনরায় সংজ্ঞা দিতে পারেন)।

কিন্তু সংগ্রহগুলি ৪.৪ থেকে একটি নতুন শ্রেণি রয়েছে, Equatorযা "টাইপের টির মধ্যে সমতা নির্ধারণ করে"। সংগ্রহসমূহ 4 সংগ্রহের উত্স কোড পরীক্ষা করার সময় তারা মনে করে যে এটি কিছু পদ্ধতিতে ব্যবহার করছে তবে যতদূর আমি এটি তৈরি করতে পারি, CardinalityHelperক্লাসটি ব্যবহার করে ফাইলের শীর্ষে থাকা পদ্ধতিগুলির জন্য এটি প্রযোজ্য নয় ... যা অন্তর্ভুক্ত disjunctionএবং intersection

আমি অবাক করে দিয়েছি যে অ্যাপাচি লোকেরা এখনও এটিকে ঘৃণ্য নয় কারণ এটি একটি তুচ্ছ নয়: আপনাকে একটি "অ্যাবস্ট্রাক্টএকটিং কোলেকশন" শ্রেণীর মতো কিছু তৈরি করতে হবে যা এর উপাদানগুলির সহজাত equalsএবং hashCodeপদ্ধতিগুলি ব্যবহার না করে পরিবর্তে সেগুলি ব্যবহার করতে হবে এর Equatorযেমন সব মৌলিক পদ্ধতিগুলির জন্য add, containsইত্যাদি বিশেষ দ্রষ্টব্য আসলে যখন আপনি সোর্স কোড তাকান, AbstractCollectionবাস্তবায়ন নেই add, কিংবা যেমন তার বিমূর্ত উপশ্রেণী না AbstractSet... আপনি যেমন কংক্রিট শ্রেণীর পর্যন্ত অপেক্ষা করতে হবে HashSetএবং ArrayListসামনে addবাস্তবায়িত হয়. বেশ মাথা ব্যথা।

মাঝামাঝি সময়ে এই স্থানটি দেখুন, আমার ধারণা। সুস্পষ্ট অন্তর্বর্তীকালীন সমাধানটি হ'ল আপনার সমস্ত উপাদানগুলিকে একটি বেসপোক র্যাপার ক্লাসে আবদ্ধ করা যা আপনি ব্যবহার করেন equalsএবং hashCodeযে ধরণের সাম্যতা আপনি চান তা প্রয়োগ করতে ... তারপরে Collectionsএই মোড়কজাতীয় বস্তুগুলি ব্যবহার করে।


এছাড়াও, বুদ্ধিমান কেউ বলেছিলেন "নির্ভরতার দাম জানুন"
স্ট্যানিস্লাও বারানস্কি

@ স্ট্যানিসলাউবারানস্কি এটি একটি আকর্ষণীয় মন্তব্য। এটি কি এমন পরামর্শ যে এই ধরনের লাইব্রেরিতে খুব বেশি নির্ভরশীল হওয়া উচিত নয়? আপনি যখন এমন একটি কম্পিউটারে কোনও ওএস ব্যবহার করেন যা ইতিমধ্যে বিশ্বাসের একটি বিশাল লাফ না? আমি অ্যাপাচি লাইব্রেরিগুলি ব্যবহার করে খুশি হওয়ার কারণ হ'ল আমি তাদের সত্যই খুব উচ্চমানের হিসাবে গ্রহণ করেছি এবং ধরে নিই যে তাদের পদ্ধতিগুলি তাদের "চুক্তি" মেনে চলে এবং পুরোপুরি পরীক্ষিত হয়েছিল tested আপনি নিজের কোডটি বিকাশ করতে কতটা সময় নিতে পারেন যা আপনি বেশি বিশ্বাস করেছিলেন? ওপেন-সোর্স অ্যাপাচি লাইব্রেরিগুলি থেকে কোডটি অনুলিপি করা এবং এটি যাচাইয়ের জন্য কিছু যাচাই করা হতে পারে ...
মাইকে রডেন্ট

8

যদি আইটেমগুলির কার্ডিনালিটি কোনও ব্যাপার না (অর্থ: পুনরাবৃত্ত উপাদানগুলিকে এক হিসাবে বিবেচনা করা হয়), তবে বাছাই না করে এটি করার একটি উপায় রয়েছে:

boolean result = new HashSet<>(listA).equals(new HashSet<>(listB));

এটি Setপ্রত্যেকের মধ্যে একটি তৈরি করবে Listএবং তারপরে HashSetএর equalsপদ্ধতিটি ব্যবহার করবে যা (অবশ্যই) আদেশকে অগ্রাহ্য করে।

কার্ডিনালিটির বিষয়টি যদি বিবেচিত হয় তবে আপনাকে অবশ্যই প্রদত্ত সুবিধার মধ্যে নিজেকে আবদ্ধ করতে হবে List; @ জেসকোইনের উত্তর সে ক্ষেত্রে আরও উপযুক্ত হবে।


যদি listA = [a, b, c, c], এবং listB = [a, b, c] হয় তবে কি হবে। ফলাফলটি সত্য হবে তবে তালিকাগুলি সমান নয়।
নিকোলাস

6

পেয়ারার মাল্টিসেটে তালিকাগুলি রূপান্তর করা খুব ভাল কাজ করে। তারা তাদের অর্ডার নির্বিশেষে তুলনা করা হয় এবং নকল উপাদানগুলিও বিবেচনায় নেওয়া হয়।

static <T> boolean equalsIgnoreOrder(List<T> a, List<T> b) {
    return ImmutableMultiset.copyOf(a).equals(ImmutableMultiset.copyOf(b));
}

assert equalsIgnoreOrder(ImmutableList.of(3, 1, 2), ImmutableList.of(2, 1, 3));
assert !equalsIgnoreOrder(ImmutableList.of(1), ImmutableList.of(1, 1));

6

এটি @cHao সমাধানের উপর ভিত্তি করে। আমি বেশ কয়েকটি সংশোধন এবং পারফরম্যান্স উন্নতি অন্তর্ভুক্ত করেছি। এটি সমান-অর্ডার-অনুলিপি সমাধানের চেয়ে প্রায় দ্বিগুণ দ্রুত চলে। যে কোনও সংগ্রহের ধরণের জন্য কাজ করে। খালি সংগ্রহ এবং নাল সমান হিসাবে গণ্য করা হয়। আপনার সুবিধার জন্য ব্যবহার করুন;)

/**
 * Returns if both {@link Collection Collections} contains the same elements, in the same quantities, regardless of order and collection type.
 * <p>
 * Empty collections and {@code null} are regarded as equal.
 */
public static <T> boolean haveSameElements(Collection<T> col1, Collection<T> col2) {
    if (col1 == col2)
        return true;

    // If either list is null, return whether the other is empty
    if (col1 == null)
        return col2.isEmpty();
    if (col2 == null)
        return col1.isEmpty();

    // If lengths are not equal, they can't possibly match
    if (col1.size() != col2.size())
        return false;

    // Helper class, so we don't have to do a whole lot of autoboxing
    class Count
    {
        // Initialize as 1, as we would increment it anyway
        public int count = 1;
    }

    final Map<T, Count> counts = new HashMap<>();

    // Count the items in col1
    for (final T item : col1) {
        final Count count = counts.get(item);
        if (count != null)
            count.count++;
        else
            // If the map doesn't contain the item, put a new count
            counts.put(item, new Count());
    }

    // Subtract the count of items in col2
    for (final T item : col2) {
        final Count count = counts.get(item);
        // If the map doesn't contain the item, or the count is already reduced to 0, the lists are unequal 
        if (count == null || count.count == 0)
            return false;
        count.count--;
    }

    // At this point, both collections are equal.
    // Both have the same length, and for any counter to be unequal to zero, there would have to be an element in col2 which is not in col1, but this is checked in the second loop, as @holger pointed out.
    return true;
}

আপনি একটি যোগ কাউন্টার ব্যবহার করে চূড়ান্ত জন্য লুপ এড়িয়ে যেতে পারেন। সমষ্টি কাউন্টার প্রতিটি পর্যায়ে মোট গণনা গণনা করা হবে। প্রথম ফর-লুপে যোগফলটি বাড়ান, এবং দ্বিতীয় লুপের জন্য এটি হ্রাস করুন। যোগফল যদি 0 এর চেয়ে বেশি হয় তবে তালিকাগুলি মেলে না, অন্যথায় তারা তা করে। বর্তমানে, চূড়ান্ত জন্য-লুপে আপনি সমস্ত গণনা শূন্য কিনা বা অন্য কথায়, সমস্ত গণনার যোগফল শূন্য কিনা তা পরীক্ষা করে দেখুন। যোগফলের ধরণের কাউন্টার ব্যবহার করে এই চেকটি বিপরীত হয়, মোট গণনাগুলির শূন্য হয় বা অন্যথায় মিথ্যা হলে সত্যটি প্রত্যাবর্তন হয়।
সাটা

আইএমও, যে-লুপগুলি তালিকার সাথে মেলে না, তখন থেকে লুপটি এড়ানো যায় (সবচেয়ে খারাপ পরিস্থিতি) ফর্ম লুপটি অপ্রয়োজনীয় ও (এন) যুক্ত করে।
সাটা

@ স্যাটা আসলে আপনি কোনও প্রতিস্থাপন ছাড়াই ২ য় লুপটি সরাতে পারেন। দ্বিতীয় লুপটি ইতিমধ্যে ফিরে আসে falseযখন কোনও কী উপস্থিত থাকে না বা এর গণনা নেতিবাচক হয়ে যায়। যেহেতু উভয় তালিকার মোট আকারের মিল রয়েছে (এটি একেবারে সামনে পরীক্ষা করা হয়েছে), দ্বিতীয় লুপের পরে শূন্য-অমূল্য পাওয়া অসম্ভব, কারণ অন্য কীটির জন্য নেতিবাচক মান ছাড়া কোনও কীটির ইতিবাচক মান থাকতে পারে না।
হলগার

@ খালি মনে হচ্ছে আপনি একেবারে সঠিক। আমি যতদূর বলতে পারি, তৃতীয় লুপটি মোটেই প্রয়োজন হয় না।
সাত

@ স্যাটা ... এবং জাভা 8 এর মাধ্যমে, এই উত্তরটির মতো এটি সংক্ষিপ্তভাবে প্রয়োগ করা যেতে পারে ।
হলগার

5

আপনি কীভাবে নিজে এটি করবেন, কোনও কম্পিউটার বা প্রোগ্রামিং ভাষার অনুপস্থিতি ভেবে দেখুন। আমি আপনাকে দুটি উপাদানের তালিকাই দেব এবং সেগুলিতে একই উপাদান রয়েছে কিনা তা আপনি আমাকে বলবেন। তুমি এটা কি ভাবে করবে?

উপরে উল্লিখিত হিসাবে একটি পন্থা হল তালিকাগুলি বাছাই করা এবং তারপরে সেগুলি সমান কিনা তা দেখার জন্য উপাদান-দ্বারা-উপাদান যেতে হবে (যা সেটাই List.equalsকরে)। এর অর্থ হয় আপনি তালিকাগুলি সংশোধন করার অনুমতি পেয়েছেন বা আপনাকে সেগুলি অনুলিপি করার অনুমতি দেওয়া হয়েছে - এবং অ্যাসাইনমেন্টটি না জেনে আমি জানতে পারি না যে উভয় / উভয়েরই অনুমতি রয়েছে কিনা।

আরেকটি পদ্ধতি হ'ল প্রতিটি তালিকার মধ্য দিয়ে যাওয়া, প্রতিটি উপাদান কতবার প্রদর্শিত হবে তা গণনা করে। যদি উভয় তালিকার শেষে একই গণনা থাকে তবে তাদের একই উপাদান রয়েছে। এর জন্য কোডটি হ'ল প্রতিটি তালিকার মানচিত্রে অনুবাদ করা elem -> (# of times the elem appears in the list)এবং তারপরে equalsদুটি মানচিত্রে কল করা। যদি মানচিত্রগুলি হয় HashMap, তবে সেই অনুবাদগুলির প্রত্যেকটিরই ও (এন) অপারেশন হয়, তুলনা করার মতো। এটি আপনাকে সময়ের সাথে একটি অতিরিক্ত দক্ষ অ্যালগরিদম দিতে চলেছে, কিছু অতিরিক্ত মেমোরির ব্যয় করে।


5

আমি একই সমস্যা ছিল এবং একটি ভিন্ন সমাধান নিয়ে এসেছি। সদৃশ জড়িত থাকাকালীন এগুলিও কাজ করে:

public static boolean equalsWithoutOrder(List<?> fst, List<?> snd){
  if(fst != null && snd != null){
    if(fst.size() == snd.size()){
      // create copied lists so the original list is not modified
      List<?> cfst = new ArrayList<Object>(fst);
      List<?> csnd = new ArrayList<Object>(snd);

      Iterator<?> ifst = cfst.iterator();
      boolean foundEqualObject;
      while( ifst.hasNext() ){
        Iterator<?> isnd = csnd.iterator();
        foundEqualObject = false;
        while( isnd.hasNext() ){
          if( ifst.next().equals(isnd.next()) ){
            ifst.remove();
            isnd.remove();
            foundEqualObject = true;
            break;
          }
        }

        if( !foundEqualObject ){
          // fail early
          break;
        }
      }
      if(cfst.isEmpty()){ //both temporary lists have the same size
        return true;
      }
    }
  }else if( fst == null && snd == null ){
    return true;
  }
  return false;
}

কিছু অন্যান্য সমাধানের তুলনায় সুবিধা:

  • O (N²) কম জটিলতার চেয়ে কম (যদিও আমি এখানে অন্যান্য উত্তরের সমাধানগুলির সাথে তুলনা করে এটির বাস্তব পারফরম্যান্স পরীক্ষা করি নি);
  • তাড়াতাড়ি প্রস্থান;
  • নাল জন্য চেক;
  • সদৃশ জড়িত থাকা সত্ত্বেও কাজ করে: আপনার যদি এখানে অ্যারে [1,2,3,3]এবং অন্য কোনও অ্যারে থাকে তবে [1,2,2,3]সর্বাধিক সমাধানগুলি অর্ডার বিবেচনা না করার সময় সেগুলি একই বলে। অস্থায়ী তালিকা থেকে সমান উপাদানগুলি সরিয়ে এই সমাধান এড়াতে পারে;
  • শব্দার্থ সমতা ব্যবহার করে ( equals) এবং রেফারেন্সের সমতা নয় ( ==);
  • এটি বাছাই করে না, সুতরাং implement Comparableএই সমাধানটি কাজ করার জন্য তাদের বাছাই করার দরকার নেই (দ্বারা )।

3

আপনি যদি সংগ্রহগুলি বাছাই করার আশা না করেন এবং আপনার ফলাফলের দরকার হয় যে ["এ" "বি" "সি"] ["বি" "বি" "এ" "সি"] এর সমান নয়,

l1.containsAll(l2)&&l2.containsAll(l1)

পর্যাপ্ত নয়, আপনাকে সম্ভবত আকারটিও পরীক্ষা করতে হবে:

    List<String> l1 =Arrays.asList("A","A","B","C");
    List<String> l2 =Arrays.asList("A","B","C");
    List<String> l3 =Arrays.asList("A","B","C");

    System.out.println(l1.containsAll(l2)&&l2.containsAll(l1));//cautions, this will be true
    System.out.println(isListEqualsWithoutOrder(l1,l2));//false as expected

    System.out.println(l3.containsAll(l2)&&l2.containsAll(l3));//true as expected
    System.out.println(isListEqualsWithoutOrder(l2,l3));//true as expected


    public static boolean isListEqualsWithoutOrder(List<String> l1, List<String> l2) {
        return l1.size()==l2.size() && l1.containsAll(l2)&&l2.containsAll(l1);
}

2

সমাধান যা সংগ্রহশালার বিয়োগ বিয়োগ পদ্ধতিতে উপকার করে:

import static org.apache.commons.collections15.CollectionUtils.subtract;

public class CollectionUtils {
  static public <T> boolean equals(Collection<? extends T> a, Collection<? extends T> b) {
    if (a == null && b == null)
      return true;
    if (a == null || b == null || a.size() != b.size())
      return false;
    return subtract(a, b).size() == 0 && subtract(a, b).size() == 0;
  }
}

1

যদি আপনি অর্ডার সম্পর্কে চিন্তা করেন তবে কেবল সমান পদ্ধতিটি ব্যবহার করুন:

list1.equals(list2)

আপনি যদি অর্ডার যত্ন না করেন তবে এটি ব্যবহার করুন

Collections.sort(list1);
Collections.sort(list2);      
list1.equals(list2)

4
সে বলেছে যে সে অর্ডার নিয়ে চিন্তা করে না
মাইক রায়ডেন্ট

0

উভয় বিশ্বের সেরা [@ দিদিজেড, @ চ্যালকোস]: এটি মূলত @ চ্যালকোস পদ্ধতি তৈরি করে তবে একটি বাগ (ifst.next ()) সংশোধন করে এবং প্রাথমিক চেকগুলি উন্নত করে (@ ডিডিজেড থেকে নেওয়া) পাশাপাশি প্রয়োজনীয়তাও সরিয়ে দেয় প্রথম সংগ্রহটি অনুলিপি করুন (কেবলমাত্র দ্বিতীয় সংগ্রহের অনুলিপি থেকে আইটেমগুলি সরিয়ে ফেলুন)।

কোনও হ্যাশিং ফাংশন বা বাছাইয়ের প্রয়োজন নেই এবং আন-সাম্যতার উপর প্রাথমিক উপস্থিতি সক্ষম করা, এটি এখনও সবচেয়ে কার্যকর বাস্তবায়ন। এটি যদি না আপনার সংগ্রহের দৈর্ঘ্য হাজার বা তার বেশি হয় এবং খুব সাধারণ হ্যাশিং ফাংশন থাকে।

public static <T> boolean isCollectionMatch(Collection<T> one, Collection<T> two) {
    if (one == two)
        return true;

    // If either list is null, return whether the other is empty
    if (one == null)
        return two.isEmpty();
    if (two == null)
        return one.isEmpty();

    // If lengths are not equal, they can't possibly match
    if (one.size() != two.size())
        return false;

    // copy the second list, so it can be modified
    final List<T> ctwo = new ArrayList<>(two);

    for (T itm : one) {
        Iterator<T> it = ctwo.iterator();
        boolean gotEq = false;
        while (it.hasNext()) {
            if (itm.equals(it.next())) {
                it.remove();
                gotEq = true;
                break;
            }
        }
        if (!gotEq) return false;
    }
    // All elements in one were found in two, and they're the same size.
    return true;
}

আমি যদি ভুল না হয়ে থাকি তবে একটি উপযুক্ত কেস দৃশ্যে এই অ্যালগরিদমের জটিলতা (যেখানে তালিকাগুলি সমান হয় তবে বিপরীত পদ্ধতিতে বাছাই করা হয়) ও (এন * এন!) হবে।
সাতা

প্রকৃতপক্ষে, এটি ও (এন * (এন / 2)) হবে, প্রতিটি পুনরাবৃত্তির সাথে অ্যারের আকার হ্রাস পাবে।
জাজগিল

0

অ্যারের তালিকার সমতা যাচাইয়ের এটি বিকল্প উপায় যা নাল মান ধারণ করতে পারে:

List listA = Arrays.asList(null, "b", "c");
List listB = Arrays.asList("b", "c", null);

System.out.println(checkEquality(listA, listB)); // will return TRUE


private List<String> getSortedArrayList(List<String> arrayList)
{
    String[] array = arrayList.toArray(new String[arrayList.size()]);

    Arrays.sort(array, new Comparator<String>()
    {
        @Override
        public int compare(String o1, String o2)
        {
            if (o1 == null && o2 == null)
            {
                return 0;
            }
            if (o1 == null)
            {
                return 1;
            }
            if (o2 == null)
            {
                return -1;
            }
            return o1.compareTo(o2);
        }
    });

    return new ArrayList(Arrays.asList(array));
}

private Boolean checkEquality(List<String> listA, List<String> listB)
{
    listA = getSortedArrayList(listA);
    listB = getSortedArrayList(listB);

    String[] arrayA = listA.toArray(new String[listA.size()]);
    String[] arrayB = listB.toArray(new String[listB.size()]);

    return Arrays.deepEquals(arrayA, arrayB);
}

তালিকা এবং অ্যারেগুলির মধ্যে এই সমস্ত অনুলিপি করার বিষয়টি কী?
হলগার

0

এই জন্য আমার সমাধান। এটি এত দুর্দান্ত নয়, তবে ভাল কাজ করে।

public static boolean isEqualCollection(List<?> a, List<?> b) {

    if (a == null || b == null) {
        throw new NullPointerException("The list a and b must be not null.");
    }

    if (a.size() != b.size()) {
        return false;
    }

    List<?> bCopy = new ArrayList<Object>(b);

    for (int i = 0; i < a.size(); i++) {

        for (int j = 0; j < bCopy.size(); j++) {
            if (a.get(i).equals(bCopy.get(j))) {
                bCopy.remove(j);
                break;
            }
        }
    }

    return bCopy.isEmpty();
}

-1

সেক্ষেত্রে {"ক", "বি"} এবং {"বি", "ক"} সমান তালিকাবদ্ধ করে। এবং {"a", "b"} এবং {"b", "a", "c"। সমান নয়। আপনি জটিল বস্তুর তালিকা ব্যবহার করেন, তাহলে মনে রাখবেন ওভাররাইড করতে সমান , পদ্ধতি হিসাবে containsAll এটা ভিতরে ব্যবহার করে।

if (oneList.size() == secondList.size() && oneList.containsAll(secondList)){
        areEqual = true;
}

-1: answer "a", "a", "b"} এবং {"a", "b", "b" with দিয়ে ভুল উত্তর দেয়: এর জন্য উত্স কোড পরীক্ষা করে দেখুন AbstractCollection.containsAll()। আমরা নকল উপাদান থাকার জন্য অনুমতি দিতে হবে যেমন আমরা কথা বলছি Lists, সে সম্পর্কে নয় Sets। আমার উত্তর দেখুন দয়া করে।
মাইকে রডেন্ট
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.