জাভা: অ্যারেলিস্টে সদৃশ সনাক্ত করুন?


104

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

অনেক ধন্যবাদ, টেরি

সম্পাদনা উল্লেখ করতে ভুলে গেছি যে আমি একে অপরের সাথে "ব্লকগুলি" তুলনা করছি না তবে তাদের পূর্ণসংখ্যার মানগুলি দেখছি। প্রতিটি "ব্লক" এর একটি ইন্টার থাকে এবং এটি তাদের আলাদা করে তোলে। "GetNum" নামের একটি পদ্ধতিতে কল করে আমি একটি নির্দিষ্ট ব্লকের অন্তর্নিহিত খুঁজে পাই (যেমন টেবিল 1 [0] [2] .getNum ();


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

তালিকা পরিবর্তে সেট ব্যবহার করুন
dmarquina

উত্তর:


192

সর্বাধিক: পুরো সংগ্রহটি একটি সেটে ফেলে দিন (সেট (সংগ্রহ) নির্মাণকারী বা সেট.এডএলএল) ব্যবহার করে, তারপরে দেখুন সেটে অ্যারেলিস্টের মতো আকার রয়েছে কিনা।

List<Integer> list = ...;
Set<Integer> set = new HashSet<Integer>(list);

if(set.size() < list.size()){
    /* There are duplicates */
}

আপডেট: আমি যদি আপনার প্রশ্নটি সঠিকভাবে বুঝতে পারি তবে আপনার মতো ব্লকের 2 ডি অ্যারে রয়েছে

ব্লক টেবিল [] [];

এবং আপনি সনাক্ত করতে চান যে তাদের কোনও সারিতে নকল রয়েছে কিনা?

সেক্ষেত্রে, ব্লক প্রয়োগগুলি "সমান" এবং "হ্যাশকোড" সঠিকভাবে প্রয়োগ করে আমি নিম্নলিখিতটি করতে পারি:

for (Block[] row : table) {
   Set set = new HashSet<Block>(); 
   for (Block cell : row) {
      set.add(cell);
   }
   if (set.size() < 6) { //has duplicate
   }
}

সিনট্যাক্সের জন্য আমি এটির 100% নিশ্চিত নই, সুতরাং এটি লিখতে এটি নিরাপদ হতে পারে

for (int i = 0; i < 6; i++) {
   Set set = new HashSet<Block>(); 
   for (int j = 0; j < 6; j++)
    set.add(table[i][j]);
 ...

Set.addযোগ করা আইটেমটি ইতিমধ্যে সেটে থাকলে বুলিয়ান মিথ্যা ফেরত দেয়, তাই আপনি শর্ট সার্কিটও করতে পারেন এবং কোনও অ্যাড থেকে বেরিয়ে falseযেতে পারেন যা আপনি জানতে চান যে কোনও ডুপ্লিকেট রয়েছে কিনা তা ফেরত দেয় returns


13
হ্যাশকোড / সমানও বাস্তবায়ন নিশ্চিত করুন।
jon077

1
বা কিছুটা সহজ: সেটটি তৈরি করার সময় এটি মোড়ানো, যেমন অ্যাডএল ব্যবহারের পরিবর্তে নতুন হ্যাশসেট (তালিকা)।
ফ্যাবিয়ান স্টেগ

2
@ jon077: এটি আপনার "নকল" এর সংজ্ঞা উপর নির্ভর করে।
মাইকেল মায়ার্স

2 ডি অ্যারেতে উপাদানগুলি সনাক্ত করার প্রক্রিয়াটি কি একই রকম হবে? উদাহরণস্বরূপ, অ্যারে [0] [0] থেকে অ্যারে [0] [6] (একটি 'সারি') থেকে চেক করা হচ্ছে ..? অনেক ধন্যবাদ, টেরি

অ্যারের প্রতিটি বস্তুর একটি পূর্ণসংখ্যার মান থাকে। "সদৃশ" দ্বারা, অবজেক্টটির সমান পূর্ণসংখ্যার মান হবে।

60

Set#addতালিকা এবং সেটের আকারের তুলনায় পরিবর্তনের কোড ব্যবহার করে উন্নত কোড ।

public static <T> boolean hasDuplicate(Iterable<T> all) {
    Set<T> set = new HashSet<T>();
    // Set#add returns false if the set does not change, which
    // indicates that a duplicate element has been added.
    for (T each: all) if (!set.add(each)) return true;
    return false;
}

7
এটা কতটা স্থান বরাদ্দ করা HashSet বলতে আরও দক্ষ করা হবে: Set<T> set = new HashSet<T>(list.size());? একটি তালিকা প্যারামিটার দেওয়া হয়েছে বলে মনে করি তালিকার সদৃশগুলি না থাকার জন্য এটি যদি সাধারণ হয় তবে এটি আরও কার্যকর।
পল জ্যাকসন

1
সম্পূর্ণ তালিকার উপর ভিত্তি করে @ পলজ্যাকসন সাইজিং সম্ভবত উপকারী হবে। তবে সাধারণ ক্ষেত্রে যদি এটির প্রথম দিকে একটি সদৃশ সন্ধান করা হয় তবে স্থানটি নষ্ট হয়েছিল। এমনকি HashSetতালিকার আকারকে আকার দেওয়ার ফলে হ্যাশ কাঠামোর অন্তর্নিহিত লোডিং ফ্যাক্টরের কারণে পুরো তালিকার মধ্য দিয়ে চলার সময় পুনরায় আকার দেওয়া হবে।
জে অ্যান্ডারসন

1
রানটাইম বা স্পেস নিয়ে আপনি যদি বাস্তব সমস্যা না পান তবে আমি আপনার কোডটি ফিনেট করব না। অকাল অপটিমাইজেশন সেরা এড়ানো হয়।
akuhn

15

আপনি যদি ডুপ্লিকেটগুলি একেবারে এড়াতে চাইছেন তবে ডুপ্লিকেট সনাক্তকরণের মাঝামাঝি প্রক্রিয়াটি কেটে নেওয়া উচিত এবং একটি সেট ব্যবহার করা উচিত ।


1
হ্যাশকোড / সমান :) বাস্তবায়ন নিশ্চিত করুন :)
jon077

@ jon077: অগত্যা, যেমনটি আমি সবে বলেছি Not
মাইকেল ম্যাইইয়ার্স

1
তবে একটি সেট ব্যবহার সদৃশ সনাক্ত করে না । এটি কেবল তাদের বাধা দেয়। অবশ্যই আপনি উপরের @akuhn দ্বারা উল্লিখিত হিসাবে অ্যাড পদ্ধতির ফলাফল চেক করুন।
mcallahan

13

সদৃশ উপাদানগুলি ফেরত দেওয়ার জন্য উন্নত কোড

  • একটি সংগ্রহে সদৃশ খুঁজে পেতে পারেন
  • সদৃশ সেট ফেরত দিন
  • সেট থেকে অনন্য উপাদান পাওয়া যাবে

public static <T> List getDuplicate(Collection<T> list) {

    final List<T> duplicatedObjects = new ArrayList<T>();
    Set<T> set = new HashSet<T>() {
    @Override
    public boolean add(T e) {
        if (contains(e)) {
            duplicatedObjects.add(e);
        }
        return super.add(e);
    }
    };
   for (T t : list) {
        set.add(t);
    }
    return duplicatedObjects;
}


public static <T> boolean hasDuplicate(Collection<T> list) {
    if (getDuplicate(list).isEmpty())
        return false;
    return true;
}

এটা বেশ দুর্দান্ত। আপনার কিছু অবৈধ কোড রয়েছে এবং সম্ভবত এটি সর্বাধিক অনুকূল উপায় নয় তবে আপনার পদ্ধতির বিষয়টি পুরোপুরি শিলা করে! (এবং এটি কাজ করে মহান)
জুল Colle,

9

যদি আপনার উপাদানগুলি কোনওরকম তুলনামূলক হয় (ক্রমানুসারে অর্ডারটির প্রকৃত অর্থ রয়েছে তা উদাসীন - এটি কেবল আপনার সাম্যের সংজ্ঞা অনুসারে সামঞ্জস্যপূর্ণ হওয়া প্রয়োজন), দ্রুততম সদৃশ অপসারণের তালিকাটি তালিকাটিকে সাজান (0 (এন লগ ( n))) তারপরে একটি একক পাস করতে হবে এবং পুনরাবৃত্ত উপাদানগুলি (যা একে অপরের অনুসরণকারী সমান উপাদানগুলি) অনুসন্ধান করবে (এটি ও (এন))।

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

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


এই ক্ষেত্রে, এন 6 হয় তাই বাস্তবায়নের বিশদগুলিতে আমি প্রচুর সময় নষ্ট করব না, তবে বিশেষ হ্যাপ সাজানোর বিষয়ে আপনার ধারণাটি রাখব যদি আমাকে এর মতো কিছু করার দরকার হয় তবে।
পল টমবলিন

আমি তৃতীয় অনুচ্ছেদ বুঝতে পারি না। মার্জোর্ট এবং হিপসোর্ট হ'ল ও (এনলগ (এন)), আপনি যেমন লেখেন তেমন ও (লগ (এন)) নয়; এমনকি যদি আপনি একবারে সদৃশ শনাক্ত করেন তবে আপনি আপনার সময়ের জটিলতা পরিবর্তন করতে পারবেন না ...
চেইমকুট

8

আমি এটার জন্য একই ধরণের অপারেশন করা দরকার Stream, তবে এর থেকে ভাল উদাহরণ খুঁজে পেলাম না। আমি যা নিয়ে এসেছি তা এখানে।

public static <T> boolean areUnique(final Stream<T> stream) {
    final Set<T> seen = new HashSet<>();
    return stream.allMatch(seen::add);
}

পুরো স্ট্রিমটি প্রক্রিয়াকরণের চেয়ে ডুপ্লিকেটগুলি প্রথম দিকে পাওয়া গেলে এবং কেবল সবকিছুকে একটি করে রাখার Setএবং আকারটি যাচাই করার চেয়ে খুব বেশি জটিল নয় যখন শর্ট সার্কিট করার সুবিধা রয়েছে । সুতরাং এই ক্ষেত্রে মোটামুটি হতে হবে:

List<T> list = ...
boolean allDistinct = areUnique(list.stream());

7

জাভা 8+ এর মাধ্যমে আপনি স্ট্রিম API ব্যবহার করতে পারেন:

boolean areAllDistinct(List<Block> blocksList) {
    return blocksList.stream().map(Block::getNum).distinct().count() == blockList.size();
}

2

সহজ কথায় বলতে হবে: 1) নিশ্চিত করুন যে সমস্ত আইটেম তুলনাযোগ্য 2) অ্যারে 2 বাছাই করুন) অ্যারে দিয়ে পুনরাবৃত্তি করুন এবং সদৃশগুলি সন্ধান করুন


1

একটি তালিকার সদৃশগুলি জানতে নিম্নলিখিত কোডটি ব্যবহার করুন: এটি আপনাকে সেই সেটটি দেবে যাতে সদৃশ রয়েছে।

 public Set<?> findDuplicatesInList(List<?> beanList) {
    System.out.println("findDuplicatesInList::"+beanList);
    Set<Object> duplicateRowSet=null;
    duplicateRowSet=new LinkedHashSet<Object>();
            for(int i=0;i<beanList.size();i++){
                Object superString=beanList.get(i);
                System.out.println("findDuplicatesInList::superString::"+superString);
                for(int j=0;j<beanList.size();j++){
                    if(i!=j){
                         Object subString=beanList.get(j);
                         System.out.println("findDuplicatesInList::subString::"+subString);
                         if(superString.equals(subString)){
                             duplicateRowSet.add(beanList.get(j));
                         }
                    }
                }
            }
            System.out.println("findDuplicatesInList::duplicationSet::"+duplicateRowSet);
        return duplicateRowSet;
  }

1

এই সমস্যাটি হ্যান্ডেল করার সর্বোত্তম উপায় হ্যাশসেট ব্যবহার করা :

ArrayList<String> listGroupCode = new ArrayList<>();
listGroupCode.add("A");
listGroupCode.add("A");
listGroupCode.add("B");
listGroupCode.add("C");
HashSet<String> set = new HashSet<>(listGroupCode);
ArrayList<String> result = new ArrayList<>(set);

কেবল ফলাফল অ্যারেলিস্ট মুদ্রণ করুন এবং ডুপ্লিকেট ছাড়াই ফলাফল দেখুন :)


1

আপনি যদি সদৃশ মানগুলির সেট চান:

import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Set;

public class FindDuplicateInArrayList {

    public static void main(String[] args) {

        Set<String> uniqueSet = new HashSet<String>();
        List<String> dupesList = new ArrayList<String>();
        for (String a : args) {
            if (uniqueSet.contains(a))
                dupesList.add(a);
            else
                uniqueSet.add(a);
        }
        System.out.println(uniqueSet.size() + " distinct words: " + uniqueSet);
        System.out.println(dupesList.size() + " dupesList words: " + dupesList);
    }
}

এবং সম্ভবত মানগুলি ছাঁটাই বা ছোট হাতের ব্যবহার সম্পর্কেও চিন্তা করুন ... আপনার ক্ষেত্রে নির্ভর করে।


আপনি যদি সদৃশ চান তবে সবচেয়ে সহজ এবং সর্বোত্তম উত্তর, পারফরম্যান্সের জন্য আপনি আরোগুলির আকারের সাথে ইউনিকসেট ইঙ্গিতটি শুরু করতে পারেন।
ক্রিস্টোফ রাউসি

0
    String tempVal = null;
    for (int i = 0; i < l.size(); i++) {
        tempVal = l.get(i); //take the ith object out of list
        while (l.contains(tempVal)) {
            l.remove(tempVal); //remove all matching entries
        }
        l.add(tempVal); //at last add one entry
    }

দ্রষ্টব্য: তালিকাটির শুরু থেকে আইটেমগুলি সরিয়ে ফেলা হলেও এটিতে বড় পারফরম্যান্স হিট হবে। এটির সমাধানের জন্য আমাদের দুটি বিকল্প রয়েছে। 1) বিপরীতে ক্রমে পুনরাবৃত্তি করুন এবং উপাদানগুলি সরান। 2) অ্যারেলিস্টের পরিবর্তে লিংকডলিস্ট ব্যবহার করুন। সাক্ষাত্কারে অন্য কোনও সংগ্রহ ব্যবহার না করে তালিকা থেকে সদৃশ অপসারণের জন্য জিজ্ঞাসা করা পক্ষপাতদুষ্ট প্রশ্নগুলির কারণে, উপরের উদাহরণটির উত্তর। বাস্তব বিশ্বে যদিও, যদি আমি এটি অর্জন করতে হয় তবে আমি তালিকা থেকে সেট থেকে সহজ উপাদানগুলিকে রেখে দেব, সহজ!


0
/**
     * Method to detect presence of duplicates in a generic list. 
     * Depends on the equals method of the concrete type. make sure to override it as required.
     */
    public static <T> boolean hasDuplicates(List<T> list){
        int count = list.size();
        T t1,t2;

        for(int i=0;i<count;i++){
            t1 = list.get(i);
            for(int j=i+1;j<count;j++){
                t2 = list.get(j);
                if(t2.equals(t1)){
                    return true;
                }
            }
        }
        return false;
    }

একটি কংক্রিট শ্রেণীর উদাহরণ যা ওভাররাইড হয়েছে equals():

public class Reminder{
    private long id;
    private int hour;
    private int minute;

    public Reminder(long id, int hour, int minute){
        this.id = id;
        this.hour = hour;
        this.minute = minute;
    }

    @Override
    public boolean equals(Object other){
        if(other == null) return false;
        if(this.getClass() != other.getClass()) return false;
        Reminder otherReminder = (Reminder) other;
        if(this.hour != otherReminder.hour) return false;
        if(this.minute != otherReminder.minute) return false;

        return true;
    }
}

0
    ArrayList<String> withDuplicates = new ArrayList<>();
    withDuplicates.add("1");
    withDuplicates.add("2");
    withDuplicates.add("1");
    withDuplicates.add("3");
    HashSet<String> set = new HashSet<>(withDuplicates);
    ArrayList<String> withoutDupicates = new ArrayList<>(set);

    ArrayList<String> duplicates = new ArrayList<String>();

    Iterator<String> dupIter = withDuplicates.iterator();
    while(dupIter.hasNext())
    {
    String dupWord = dupIter.next();
    if(withDuplicates.contains(dupWord))
    {
        duplicates.add(dupWord);
    }else{
        withoutDupicates.add(dupWord);
    }
    }
  System.out.println(duplicates);
  System.out.println(withoutDupicates);

এই উত্তরটি কীভাবে চলতি সমস্যা সমাধানে
ওপিকে

0

এই উত্তরটি কোটলিনে কব্জিযুক্ত তবে জাভাতে সহজেই অনুবাদ করা যায়।

যদি আপনার অ্যারেলিস্টের আকারটি একটি নির্দিষ্ট ছোট পরিসরের মধ্যে থাকে তবে এটি একটি দুর্দান্ত সমাধান।

var duplicateDetected = false
    if(arrList.size > 1){
        for(i in 0 until arrList.size){
            for(j in 0 until arrList.size){
                if(i != j && arrList.get(i) == arrList.get(j)){
                    duplicateDetected = true
                }
            }
        }
    }

0
private boolean isDuplicate() {
    for (int i = 0; i < arrayList.size(); i++) {
        for (int j = i + 1; j < arrayList.size(); j++) {
            if (arrayList.get(i).getName().trim().equalsIgnoreCase(arrayList.get(j).getName().trim())) {
                return true;
            }
        }
    }

    return false;
}
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.