অ্যারেতে উপাদান খুঁজে পেতে রুবিয়ের এগারোটি পদ্ধতি রয়েছে।
include?পছন্দসইটি হ'ল বা, বারবার অ্যাক্সেসের জন্য একটি সেট তৈরি করুন এবং তারপরে কল করুন include?বাmember? ।
তাদের সব এখানে:
array.include?(element) # preferred method
array.member?(element)
array.to_set.include?(element)
array.to_set.member?(element)
array.index(element) > 0
array.find_index(element) > 0
array.index { |each| each == element } > 0
array.find_index { |each| each == element } > 0
array.any? { |each| each == element }
array.find { |each| each == element } != nil
array.detect { |each| each == element } != nil
trueউপাদান উপস্থিত থাকলে তারা সকলেই একটি ইশ মান প্রদান করে।
include?পছন্দসই পদ্ধতি। এটি forঅভ্যন্তরীণভাবে সি-ভাষার লুপ ব্যবহার করে যা কোনও উপাদান অভ্যন্তরীণ rb_equal_opt/rb_equalফাংশনগুলির সাথে মিলে গেলে বিরতি দেয়। আপনি পুনরাবৃত্ত সদস্যতার পরীক্ষার জন্য একটি সেট তৈরি না করলে এটি আরও বেশি দক্ষ হতে পারে না।
VALUE
rb_ary_includes(VALUE ary, VALUE item)
{
long i;
VALUE e;
for (i=0; i<RARRAY_LEN(ary); i++) {
e = RARRAY_AREF(ary, i);
switch (rb_equal_opt(e, item)) {
case Qundef:
if (rb_equal(e, item)) return Qtrue;
break;
case Qtrue:
return Qtrue;
}
}
return Qfalse;
}
member?Arrayক্লাসে নতুন সংজ্ঞা দেওয়া হয়নি এবং Enumerableমডিউল থেকে একটি নিরবচ্ছিন্ন বাস্তবায়ন ব্যবহার করে যা আক্ষরিকভাবে সমস্ত উপাদানগুলির মাধ্যমে অঙ্কিত হয়:
static VALUE
member_i(RB_BLOCK_CALL_FUNC_ARGLIST(iter, args))
{
struct MEMO *memo = MEMO_CAST(args);
if (rb_equal(rb_enum_values_pack(argc, argv), memo->v1)) {
MEMO_V2_SET(memo, Qtrue);
rb_iter_break();
}
return Qnil;
}
static VALUE
enum_member(VALUE obj, VALUE val)
{
struct MEMO *memo = MEMO_NEW(val, Qfalse, 0);
rb_block_call(obj, id_each, 0, 0, member_i, (VALUE)memo);
return memo->v2;
}
রুবি কোড অনুবাদিত এটি নিম্নলিখিত সম্পর্কে:
def member?(value)
memo = [value, false, 0]
each_with_object(memo) do |each, memo|
if each == memo[0]
memo[1] = true
break
end
memo[1]
end
উভয় include?এবংmember? ও (এন) সময় জটিলতা রয়েছে যেহেতু উভয়ই প্রত্যাশিত মানটির প্রথম উপস্থিতির জন্য অ্যারেটি অনুসন্ধান করে।
আমরা প্রথমে অ্যারের উপস্থাপনের জন্য একটি হ্যাশ প্রতিনিধিত্ব তৈরি করতে ব্যয় করে ও (1) অ্যাক্সেস সময় পাওয়ার জন্য একটি সেট ব্যবহার করতে পারি। আপনি যদি বারবার একই অ্যারেতে সদস্যতা পরীক্ষা করেন তবে এই প্রাথমিক বিনিয়োগটি দ্রুত পরিশোধ করতে পারে। Setসি তে প্রয়োগ করা হয়নি তবে প্লেইন রুবি শ্রেণি হিসাবে এখনও অন্তর্নিহিত এর ও (1) অ্যাক্সেস সময়@hash এটিকে সার্থক করে তোলে।
এখানে সেট শ্রেণীর বাস্তবায়ন:
module Enumerable
def to_set(klass = Set, *args, &block)
klass.new(self, *args, &block)
end
end
class Set
def initialize(enum = nil, &block) # :yields: o
@hash ||= Hash.new
enum.nil? and return
if block
do_with_enum(enum) { |o| add(block[o]) }
else
merge(enum)
end
end
def merge(enum)
if enum.instance_of?(self.class)
@hash.update(enum.instance_variable_get(:@hash))
else
do_with_enum(enum) { |o| add(o) }
end
self
end
def add(o)
@hash[o] = true
self
end
def include?(o)
@hash.include?(o)
end
alias member? include?
...
end
আপনি দেখতে পাচ্ছেন যে সেট শ্রেণিটি কেবল একটি অভ্যন্তরীণ @hashউদাহরণ তৈরি করে , এতে সমস্ত বস্তু ম্যাপ করেtrueHash#include? , হ্যাশ ক্লাসে ও (1) অ্যাক্সেসের সময় প্রয়োগ করা হয় যা ব্যবহার করে এবং তারপরে সদস্যতা পরীক্ষা করে ।
আমি অন্য সাতটি পদ্ধতি নিয়ে আলোচনা করব না কারণ এগুলি সবই কম দক্ষ।
ও (এন) জটিলতার সাথে উপরের তালিকাভুক্ত ১১ টির বাইরে আরও অনেকগুলি পদ্ধতি রয়েছে তবে আমি তাদের তালিকা না দেওয়ার সিদ্ধান্ত নিয়েছি কারণ তারা প্রথম ম্যাচে ব্রেক করার চেয়ে পুরো অ্যারে স্ক্যান করে।
এগুলি ব্যবহার করবেন না:
# bad examples
array.grep(element).any?
array.select { |each| each == element }.size > 0
...