কোটলিনে ভাঁজ এবং হ্রাসের মধ্যে মৌলিক পার্থক্য কী? কখন ব্যবহার করবেন?


130

আমি এই উভয় ফাংশন fold()এবং reduce()কোটলিনে খুব বিভ্রান্ত , কেউ কি আমাকে একটি দৃ me় উদাহরণ দিতে পারেন যা উভয়কেই আলাদা করে?



4
একটি সময়ে কটাক্ষপাত আছে এই এই বিষয়ে গভীর মৌলিক আলোচনার জন্য
GhostCat

2
@ লুনার ওয়াটার, আমি এই ডকগুলি দেখেছি, কিন্তু এটি পাচ্ছি না, এটিই আপনি প্রশ্ন পোস্ট করেছেন, আপনি উদাহরণ দিতে পারেন?
তপন এইচপি

1
@ ম্যাটক্লেইন করেছেন
মিনার্ড

উত্তর:


280

fold একটি প্রাথমিক মান নেয় এবং আপনি যে ল্যাম্বডায় পাস করেন তার প্রথম অনুরোধটি সেই প্রাথমিক মানটি এবং পরামিতি হিসাবে সংগ্রহের প্রথম উপাদানটি গ্রহণ করবে।

উদাহরণস্বরূপ, নিম্নলিখিত কোডটি নিন যা পূর্ণসংখ্যার তালিকার সমষ্টি গণনা করে:

listOf(1, 2, 3).fold(0) { sum, element -> sum + element }

ল্যাম্বডায় প্রথম কলটি প্যারামিটার সহ 0এবং থাকবে 1

আপনার ক্রিয়াকলাপের জন্য যদি আপনাকে কোনও ধরণের ডিফল্ট মান বা প্যারামিটার সরবরাহ করতে হয় তবে প্রাথমিক মানটিতে পাস করার ক্ষমতাটি কার্যকর। উদাহরণস্বরূপ, আপনি যদি কোনও তালিকার মধ্যে সর্বাধিক মান সন্ধান করেন তবে কোনও কারণে কমপক্ষে 10 টি ফিরে আসতে চান, আপনি নিম্নলিখিতটি করতে পারেন:

listOf(1, 6, 4).fold(10) { max, element ->
    if (element > max) element else max
}

reduceপ্রাথমিক মান গ্রহণ করে না, তবে পরিবর্তে সংগ্রহের প্রথম উপাদানটির সাথে শুরু হয় ( sumনিম্নলিখিত উদাহরণে বলা হয়)।

উদাহরণস্বরূপ, আসুন আবার সংখ্যার যোগফল করব:

listOf(1, 2, 3).reduce { sum, element -> sum + element }

এখানে ল্যাম্বডায় প্রথম কলটি হবে প্যারামিটার 1এবং সহ 2

আপনি reduceযখন ব্যবহার করতে পারেন তখন আপনার অপারেশন আপনি যে সংগ্রহটিতে প্রয়োগ করছেন সেগুলি বাদে অন্য কোনও মানের উপর নির্ভর করে না।


47
ভাল ব্যাখ্যা! আমি আরও বলব, খালি সংগ্রহটি হ্রাস করা যাবে না, তবে ভাঁজ করা যেতে পারে।
মিহা_এক্স 64

দেখুন, আমি কোটলিনের একেবারে প্রাথমিক স্তরে, আপনি যে প্রথম উদাহরণটি দিয়েছেন তা কি আপনি কিছু পদক্ষেপ এবং চূড়ান্ত উত্তর দিয়ে আরও ব্যাখ্যা করতে পারেন? দুর্দান্ত সাহায্য হবে
তপন এইচপি

3
@ তপানএইচপি emptyList<Int>().reduce { acc, s -> acc + s }একটি ব্যতিক্রম উত্পাদন করবে, তবে emptyList<Int>().fold(0) { acc, s -> acc + s }তা ঠিক আছে।
মিহা_এক্স 64

31
হ্রাস এছাড়াও লাম্বদা ফেরত তালিকার সদস্যদের মতো একই ধরণের হতে বাধ্য করে, যা ভাঁজ সহ সত্য নয়। এটি তালিকার প্রথম উপাদানটি, সঞ্চয়ের প্রাথমিক মূল্য তৈরির একটি গুরুত্বপূর্ণ পরিণতি।
andresp

4
@ অনার্স: সম্পূর্ণতার জন্য একটি নোট হিসাবে: এটি একই ধরণের হতে হবে না । তালিকার সদস্যরাও সংগ্রহকারীর একটি উপ listOf<Int>(1, 2).reduce { acc: Number, i: Int -> acc.toLong() + i }-টাইপ হতে পারে: এটি কাজ করে (তালিকা-টাইপটি ইন্ট থাকে এবং
বরিস

11

আমি যে বড় কার্যকরী পার্থক্যটি কল করব (যা অন্য উত্তরের মন্তব্যে উল্লেখ করা হয়েছে, তবে বুঝতে অসুবিধা হতে পারে) এটি খালি সংগ্রহের ক্ষেত্রে সঞ্চালিত হলে reduce ব্যতিক্রম ঘটায়।

listOf<Int>().reduce { x, y -> x + y }
// java.lang.UnsupportedOperationException: Empty collection can't be reduced.

এটি কারণ .reduce"ডেটা নেই" ইভেন্টে কোন মানটি ফিরবে তা জানেন না।

.foldএটির সাথে বৈসাদৃশ্য করুন , যার জন্য আপনাকে "শুরুর মান" সরবরাহ করতে হবে যা খালি সংগ্রহের ক্ষেত্রে ডিফল্ট মান হবে:

val result = listOf<Int>().fold(0) { x, y -> x + y }
assertEquals(0, result)

সুতরাং, এমনকি যদি আপনি আপনার সংগ্রহটি আলাদা (অ-সম্পর্কিত) ধরণের (যা কেবল .foldআপনাকে করতে দেয়) একক উপাদানে একত্রিত করতে না চান , তবে যদি আপনার প্রারম্ভিক সংগ্রহটি খালি থাকতে পারে তবে আপনাকে অবশ্যই সংগ্রহ সংগ্রহ করে দেখুন আকারটি প্রথমে এবং তারপরে .reduceবা কেবল ব্যবহার করুন.fold

val collection: List<Int> = // collection of unknown size

val result1 = if (collection.isEmpty()) 0
              else collection.reduce { x, y -> x + y }

val result2 = collection.fold(0) { x, y -> x + y }

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