জাভাতে সংগ্রহ থেকে বিতরণ গণনা করুন

সংখ্যার একটি সংগ্রহ (অথবা যে বস্তুর ক্ষেত্রগুলি আপনি পরিদর্শন করতে চান) সেই সংখ্যাগুলির একটি বিতরণে পরিণত করা একটি সাধারণ পরিসংখ্যান কৌশল, এবং রিপোর্টিং এবং ডেটা-চালিত অ্যাপ্লিকেশনগুলিতে বিভিন্ন প্রসঙ্গে নিযুক্ত করা হয়।

একটি সংগ্রহ দেওয়া হয়েছে:

1, 1, 2, 1, 2, 3, 1, 4, 5, 1, 3

আপনি গণনা হিসাবে তাদের বিতরণ পরিদর্শন করতে পারেন (প্রতিটি উপাদানের ফ্রিকোয়েন্সি), এবং ফলাফলগুলি একটি মানচিত্রে সংরক্ষণ করতে পারেন:

{
"1": 5,
"2": 2,
"3": 2,
"4": 1,
"5": 1
}

বা, আপনি পারেন স্বাভাবিক করা মানগুলির মোট সংখ্যার উপর ভিত্তি করে মানগুলি - এইভাবে সেগুলিকে শতাংশে প্রকাশ করে:

{
"1": 0.45,
"2": 0.18,
"3": 0.18,
"4": 0.09,
"5": 0.09
}

অথবা এমনকি এই শতাংশগুলিকে a এ প্রকাশ করুন 0..100 a এর পরিবর্তে বিন্যাস 0..1 বিন্যাস।

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

জাভাতে কার্যকরী প্রোগ্রামিং সমর্থন যোগ করার সাথে - বিতরণ গণনা করা আগের চেয়ে সহজ। আমরা সংখ্যার সংগ্রহ এবং এর একটি সংগ্রহ নিয়ে কাজ করব Books:

public class Book {

    private String id;
    private String name;
    private String author;
    private long pageNumber;
    private long publishedYear;

   
}

জাভাতে সংগ্রহের বিতরণ গণনা করুন

আসুন প্রথমে দেখে নেওয়া যাক কিভাবে আপনি আদিম প্রকারের জন্য একটি বিতরণ গণনা করতে পারেন। বস্তুর সাথে কাজ করা আপনাকে গণনায় আরও নমনীয়তা প্রদান করতে আপনার ডোমেন ক্লাস থেকে কাস্টম পদ্ধতিতে কল করার অনুমতি দেয়।

ডিফল্টরূপে, আমরা শতাংশগুলিকে দ্বিগুণ হিসাবে উপস্থাপন করব 0.00 থেকে 100.00.

আদিম প্রকার

আসুন পূর্ণসংখ্যার একটি তালিকা তৈরি করি এবং তাদের বিতরণ মুদ্রণ করি:

List integerList = List.of(1, 1, 2, 1, 2, 3, 1, 4, 5, 1, 3);
System.out.println(calculateIntegerDistribution(integerList));

বিতরণ গণনা করা হয়:

public static Map calculateIntegerDistribution(List list) {
    return list.stream()
            .collect(Collectors.groupingBy(Integer::intValue,
                    Collectors.collectingAndThen(Collectors.counting(),
                            count -> (Double.parseDouble(String.format("%.2f", count * 100.00 / list.size()))))));
}

এই পদ্ধতিটি একটি তালিকা গ্রহণ করে এবং এটি স্ট্রিম করে। স্ট্রিম করার সময়, মানগুলি হল৷ দ্বারা গোষ্ঠীবদ্ধ তাদের পূর্ণসংখ্যা মান - এবং তাদের মান হয় সংখ্যাত ব্যবহার Collectors.counting(), একটি মধ্যে সংগ্রহ করার আগে Map যেখানে কীগুলি ইনপুট মানগুলিকে উপস্থাপন করে এবং দ্বিগুণগুলি বিতরণে তাদের শতাংশকে উপস্থাপন করে।

এখানে মূল পদ্ধতি হল collect() যা গ্রহণ করে দুই সংগ্রাহক. কী-সংগ্রাহক কেবল কী মান (ইনপুট উপাদান) দ্বারা গোষ্ঠীবদ্ধ করে সংগ্রহ করে। মূল্য সংগ্রাহক এর মাধ্যমে সংগ্রহ করে collectingAndThen() পদ্ধতি, যা আমাদের অনুমতি দেয় মান গণনা এবং তারপরে সেগুলিকে অন্য বিন্যাসে বিন্যাস করুন, যেমন count * 100.00 / list.size() যা আমাদের গণনা করা উপাদানগুলিকে শতাংশে প্রকাশ করতে দেয়:

{1=45.45, 2=18.18, 3=18.18, 4=9.09, 5=9.09}

মান বা কী দ্বারা বন্টন সাজান

ডিস্ট্রিবিউশন তৈরি করার সময় - আপনি সাধারণত মানগুলি সাজাতে চাইবেন। আরো প্রায়ই না, এই দ্বারা হবে চাবি. জাভা HashMaps সন্নিবেশের আদেশ সংরক্ষণের গ্যারান্টি দেবেন না, তাই আমরা একটি ব্যবহার করতে হবে LinkedHashMap যা আছে. অতিরিক্তভাবে, মানচিত্রটিকে পুনরায় স্ট্রিম করা এবং এখন এটিকে পুনরায় সংগ্রহ করা সবচেয়ে সহজ কারণ এটি অনেক ছোট আকারের এবং অনেক বেশি পরিচালনাযোগ্য৷

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

public static Map calculateIntegerDistribution(List list) {
    return list.stream()
            .collect(Collectors.groupingBy(Integer::intValue,
                    Collectors.collectingAndThen(Collectors.counting(),
                            count -> (Double.parseDouble(String.format("%.2f", count.doubleValue() / list.size()))))))
            
            
            .entrySet()
            .stream()
            .sorted(Map.Entry.comparingByKey())
            .collect(Collectors.toMap(e -> Integer.parseInt(e.getKey().toString()),
                    Map.Entry::getValue,
                    (a, b) -> {
                        throw new AssertionError();
                    },
                    LinkedHashMap::new));
}

অবজেক্টস

কিভাবে এটি বস্তুর জন্য করা যেতে পারে? একই যুক্তি প্রযোজ্য! একটি সনাক্তকরণ ফাংশনের পরিবর্তে (Integer::intValue), আমরা পরিবর্তে পছন্দসই ক্ষেত্র ব্যবহার করব – যেমন আমাদের বইয়ের জন্য প্রকাশিত বছর। আসুন কয়েকটি বই তৈরি করি, সেগুলিকে একটি তালিকায় সংরক্ষণ করি এবং তারপর প্রকাশনা বছরের বিতরণ গণনা করি:

সেরা-অভ্যাস, শিল্প-স্বীকৃত মান এবং অন্তর্ভুক্ত চিট শীট সহ গিট শেখার জন্য আমাদের হ্যান্ডস-অন, ব্যবহারিক গাইড দেখুন। গুগলিং গিট কমান্ড এবং আসলে বন্ধ করুন শেখা এটা!

Book book1 = new Book("001", "Our Mathematical Universe", "Max Tegmark", 432, 2014);
Book book2 = new Book("002", "Life 3.0", "Max Tegmark", 280, 2017);
Book book3 = new Book("003", "Sapiens", "Yuval Noah Harari", 443, 2011);
Book book4 = new Book("004", "Steve Jobs", "Water Isaacson", 656, 2011);

List books = Arrays.asList(book1, book2, book3, book4);

এর বিতরণ গণনা করা যাক publishedYear ক্ষেত্র:

public static Map calculateDistribution(List books) {
    return books.stream()
            .collect(Collectors.groupingBy(Book::getPublishedYear,
                    Collectors.collectingAndThen(Collectors.counting(),
                            count -> (Double.parseDouble(String.format("%.2f", count * 100.00 / books.size()))))))
            
            .entrySet()
            .stream()
            .sorted(Map.Entry.comparingByKey())
            .collect(Collectors.toMap(e -> Integer.parseInt(e.getKey().toString()),
                    Map.Entry::getValue,
                    (a, b) -> {
                        throw new AssertionError();
                    },
                    LinkedHashMap::new));
}

সমন্বয় করা "%.2f" ফ্লোটিং পয়েন্ট নির্ভুলতা সেট করতে। এর ফলে:

{2011=50.0, 2014=25.0, 2017=25.0}

প্রদত্ত বইগুলির 50% (2/4) 2011 সালে প্রকাশিত হয়েছিল, 25% (1/4) 2014 সালে এবং 25% (1/4) 2017 সালে প্রকাশিত হয়েছিল। আপনি যদি এই ফলাফলটিকে ভিন্নভাবে ফর্ম্যাট করতে চান এবং স্বাভাবিক করতে চান তবে কী হবে মধ্যে পরিসীমা 0..1?

জাভাতে সংগ্রহের সাধারণীকৃত (শতাংশ) বিতরণ গণনা করুন

একটি থেকে শতাংশ স্বাভাবিক করার জন্য 0.0...100.0 পরিসীমা a 0..1 পরিসীমা - আমরা সহজভাবে মানিয়ে নেব collectingAndThen() ডেকে আনো না দ্বারা গণনা গুণ করুন 100.0 সংগ্রহের আকার দ্বারা ভাগ করার আগে।

পূর্বে, Long দ্বারা ফেরত গণনা Collectors.counting() পরোক্ষভাবে একটি দ্বিগুণে রূপান্তরিত হয়েছিল (একটি দ্বিগুণ মানের সাথে গুণ) - তাই এই সময়, আমরা স্পষ্টভাবে পেতে চাই doubleValue() এর count:

    public static Map calculateDistributionNormalized(List books) {
        return books.stream()
            .collect(Collectors.groupingBy(Book::getPublishedYear,
                    Collectors.collectingAndThen(Collectors.counting(),
                            count -> (Double.parseDouble(String.format("%.4f", count.doubleValue() / books.size()))))))
            
            .entrySet()
            .stream()
            .sorted(comparing(e -> e.getKey()))
            .collect(Collectors.toMap(e -> Integer.parseInt(e.getKey().toString()),
                    Map.Entry::getValue,
                    (a, b) -> {
                        throw new AssertionError();
                    },
                    LinkedHashMap::new));
}

সমন্বয় করা "%.4f" ফ্লোটিং পয়েন্ট নির্ভুলতা সেট করতে। এর ফলে:

{2011=0.5, 2014=0.25, 2017=0.25}

সংগ্রহের উপাদান গণনা (ফ্রিকোয়েন্সি) গণনা করুন

পরিশেষে – আমরা সংগ্রহের আকার দ্বারা গণনাকে ভাগ না করে সংগ্রহে উপাদান গণনা (সমস্ত উপাদানের ফ্রিকোয়েন্সি) পেতে পারি! এটি একটি সম্পূর্ণ অ-স্বাভাবিক গণনা:

   public static Map calculateDistributionCount(List books) {
        return books
            .stream()
            .collect(Collectors.groupingBy(Book::getPublishedYear,
                    Collectors.collectingAndThen(Collectors.counting(),
                            count -> (Integer.parseInt(String.format("%s", count.intValue()))))))
            
            .entrySet()
            .stream()
            .sorted(Map.Entry.comparingByKey())
            .collect(Collectors.toMap(e -> Integer.parseInt(e.getKey().toString()),
                    Map.Entry::getValue,
                    (a, b) -> {
                        throw new AssertionError();
                    },
                    LinkedHashMap::new));
}

এর ফলে:

{2011=2, 2014=1, 2017=1}

প্রকৃতপক্ষে, 2011-এর দুটি বই এবং 2014 এবং 2017-এর একটি করে।

উপসংহার

ডেটা বিতরণ গণনা করা ডেটা সমৃদ্ধ অ্যাপ্লিকেশনগুলিতে একটি সাধারণ কাজ, এবং এর জন্য বাহ্যিক লাইব্রেরি বা জটিল কোড ব্যবহারের প্রয়োজন হয় না। কার্যকরী প্রোগ্রামিং সমর্থন সহ, জাভা সংগ্রহগুলিকে একটি হাওয়ায় পরিণত করেছে!

এই সংক্ষিপ্ত খসড়াটিতে, আমরা দেখেছি যে আপনি কীভাবে একটি সংগ্রহের সমস্ত উপাদানের ফ্রিকোয়েন্সি গণনা করতে পারেন, সেইসাথে কীভাবে শতাংশে স্বাভাবিক করা বিতরণ মানচিত্র গণনা করবেন 0 এবং 1 সেইসাথে 0 এবং 100 জাভাতে।

সময় স্ট্যাম্প:

থেকে আরো Stackabuse