রুবিতে অবজেক্ট অ্যাট্রিবিউট অনুসারে ইউনিক


126

এক বা একাধিক বৈশিষ্ট্যের প্রতি সম্মানজনক যে কোনও অ্যারেতে অবজেক্টগুলি নির্বাচন করার সর্বাধিক মার্জিত উপায় কী?

এই বস্তুগুলি অ্যাক্টিভেকর্ডে সংরক্ষণ করা হয় তাই এআর এর পদ্ধতিগুলি ব্যবহার করাও ভাল।

উত্তর:


200

Array#uniqএকটি ব্লক ব্যবহার করুন :

@photos = @photos.uniq { |p| p.album_id }

5
এটি রুবি ১.৯ এবং পরবর্তী সংস্করণগুলির সঠিক উত্তর ।
নুরেটিন

2
+1 টি। এবং পূর্বের রুবীদের জন্য সর্বদা এখানে রয়েছে require 'backports':-)
মারক-আন্দ্রে লাফোর্টুন

হ্যাশ পদ্ধতিটি যদি আপনি অ্যালবাম_আইডি দ্বারা দলবদ্ধ করতে চান তবে নাম_প্লেগুলি যোগ করে (বলুন) ভাল।
thekingoftruth

20
আপনি এটি-টুপ্রোক ( রুবি- ডক.আর.অর্গ.ও.কোয়ার ১.৯.৩ / সিম্বল এইচটিএমএল # মেমোডি- টু_প্রোক ) দিয়ে এটি উন্নত করতে পারেন :@photos.uniq &:album_id
জুমোমিলহো

রুবির ১.৮ এর জন্য @ ব্রাবলিবো আপনাকে ঠিক এই একই এসওতে পড়তে হবে: stackoverflow.com/a/113770/213191
পিটার এইচ বোলিং

22

uniq_byআপনার প্রকল্পে অ্যারেতে পদ্ধতিটি যুক্ত করুন । এটি সাথে সাদৃশ্য দ্বারা কাজ করে sort_by। সুতরাং uniq_byহয় uniqযেমন sort_byহয় sort। ব্যবহার:

uniq_array = my_array.uniq_by {|obj| obj.id}

রুপায়ণ:

class Array
  def uniq_by(&blk)
    transforms = []
    self.select do |el|
      should_keep = !transforms.include?(t=blk[el])
      transforms << t
      should_keep
    end
  end
end

মনে রাখবেন যে এটি আপনার বর্তমানের জায়গায় পরিবর্তনের পরিবর্তে একটি নতুন অ্যারে প্রদান করে। আমরা একটি লিখিনিuniq_by! পদ্ধতি লিখিনি তবে আপনি চাইলে এটি যথেষ্ট সহজ হওয়া উচিত।

সম্পাদনা: উপজাতীয়গণ উল্লেখ করেছেন যে বাস্তবায়নটি হ'ল (এন ^ 2)। এর চেয়ে ভাল কিছু হবে (অদৃশিত) ...

class Array
  def uniq_by(&blk)
    transforms = {}
    select do |el|
      t = blk[el]
      should_keep = !transforms[t]
      transforms[t] = true
      should_keep
    end
  end
end

1
দুর্দান্ত এপিআই তবে এটি দুর্দান্ত (ও (এন ^ 2) এর মতো দেখতে) বড় অ্যারেগুলির জন্য স্কেলিং কর্মক্ষমতা রয়েছে। একটি হ্যাশসেট রূপান্তর করে স্থির করা যায়।
উপজাতিরা

7
এই উত্তরটি পুরানো। রুবি> = 1.9 এর অ্যারে # ইউনিকের সাথে একটি ব্লক রয়েছে যা ঠিক এটি করে, যেমন গৃহীত উত্তরের হিসাবে।
পিটার এইচ। বলিং

17

এটি ডাটাবেস স্তরে করুন:

YourModel.find(:all, :group => "status")

1
এবং যদি এটি একাধিক ক্ষেত্র, আগ্রহের বাইরে ছিল?
রায়ান বিগ

12

আপনি এই কৌশলটি অ্যারে থেকে বিভিন্ন বৈশিষ্ট্য উপাদান দ্বারা অনন্য নির্বাচন করতে ব্যবহার করতে পারেন:

@photos = @photos.uniq { |p| [p.album_id, p.author_id] }

খুব স্পষ্ট, তাই রুবি। রুবিকে আশীর্বাদ করার আরও একটি কারণ
টুটেনমিলান

6

আমি মূলত selectঅ্যারেতে পদ্ধতিটি ব্যবহার করার পরামর্শ দিয়েছিলাম । বুদ্ধিমান:

[1, 2, 3, 4, 5, 6, 7].select{|e| e%2 == 0} আমাদের দেয় [2,4,6] ফিরিয়ে

আপনি যদি এই জাতীয় প্রথম জিনিসটি চান তবে ব্যবহার করুন detect

[1, 2, 3, 4, 5, 6, 7].detect{|e| e>3} আমাদের দেয় 4

যদিও আপনি এখানে যাচ্ছেন সে সম্পর্কে আমি নিশ্চিত নই।


5

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

objs.inject({}) {|h,e| h[e.attr]=e; h}.values

এটি দুর্দান্ত 1-লাইনার, তবে আমার সন্দেহ হয় এটি সম্ভবত আরও দ্রুত হতে পারে:

h = {}
objs.each {|e| h[e.attr]=e}
h.values

3

যদি আমি আপনার প্রশ্নটি সঠিকভাবে বুঝতে পারি, তবে কোনও বৈশিষ্ট্য পৃথক কিনা তা নির্ধারণ করার জন্য আমি মার্শাল বস্তুগুলির সাথে তুলনা করার আধা-হ্যাকি পদ্ধতির সাহায্যে এই সমস্যাটি মোকাবিলা করেছি। নিম্নলিখিত কোডের শেষে ইঞ্জেকশনটি উদাহরণ হতে পারে:

class Foo
  attr_accessor :foo, :bar, :baz

  def initialize(foo,bar,baz)
    @foo = foo
    @bar = bar
    @baz = baz
  end
end

objs = [Foo.new(1,2,3),Foo.new(1,2,3),Foo.new(2,3,4)]

# find objects that are uniq with respect to attributes
objs.inject([]) do |uniqs,obj|
  if uniqs.all? { |e| Marshal.dump(e) != Marshal.dump(obj) }
    uniqs << obj
  end
  uniqs
end

3

সর্বাধিক মার্জিত উপায় আমি খুঁজে পেয়েছি Array#uniqএকটি ব্লক ব্যবহার করে একটি স্পিন অফ

enumerable_collection.uniq(&:property)

… এটি আরও ভাল পড়া!


2

আপনি একটি হ্যাশ ব্যবহার করতে পারেন, এতে প্রতিটি কীগুলির জন্য কেবল একটি মান রয়েছে:

Hash[*recs.map{|ar| [ar[attr],ar]}.flatten].values



1

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

h = Set.new
objs.select{|el| h.add?(el.attr)}


0

এখন আপনি যদি বৈশিষ্ট্যটির মানগুলি বাছাই করতে পারেন তবে এটি করা যেতে পারে:

class A
  attr_accessor :val
  def initialize(v); self.val = v; end
end

objs = [1,2,6,3,7,7,8,2,8].map{|i| A.new(i)}

objs.sort_by{|a| a.val}.inject([]) do |uniqs, a|
  uniqs << a if uniqs.empty? || a.val != uniqs.last.val
  uniqs
end

এটি একটি 1-গুণাবলীর অনন্য জন্য, তবে একই জিনিস ডাব্লু / লিক্সোগ্রাফিকাল সাজান ...

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