https://bugs.ruby-lang.org/https://bugs.ruby-lang.org/favicon.ico?17113305112019-12-17T14:31:59ZRuby Issue Tracking SystemRuby master - Feature #16428: Add Array#uniq?, Enumerable#uniq?https://bugs.ruby-lang.org/issues/16428?journal_id=831942019-12-17T14:31:59Zshevegen (Robert A. Heiler)shevegen@gmail.com
<ul></ul><blockquote>
<p>I often need to check if an array have duplicate elements.</p>
</blockquote>
<p>Makes sense to me; I have had situations where I needed this<br>
too in the past (including situations for non-unique entries<br>
in an Array), so I agree on the general use case opportunities<br>
in this regard.</p> Ruby master - Feature #16428: Add Array#uniq?, Enumerable#uniq?https://bugs.ruby-lang.org/issues/16428?journal_id=832052019-12-18T05:02:42Zduerst (Martin Dürst)duerst@it.aoyama.ac.jp
<ul></ul><p>I seem to member that many years ago, I made the same proposal, and Nobu created a patch, but unfortunately, I didn't find any traces anymore on this tracker or in my mail.</p>
<p>Anyway, I support this proposal. It's definitely an useful functionality, and it's clearly faster than doing it indirectly via #uniq.</p> Ruby master - Feature #16428: Add Array#uniq?, Enumerable#uniq?https://bugs.ruby-lang.org/issues/16428?journal_id=832072019-12-18T06:50:39Zkyanagi (Kouhei Yanagita)
<ul><li><strong>Subject</strong> changed from <i>Add Array#uniq?</i> to <i>Add Array#uniq?, Enumerable#uniq?</i></li></ul><p>Following a suggestion of <code>Enumerable#uniq?</code>, I also added <code>Enumerable#uniq?</code> to my patch.<br>
<code>Array#uniq?</code> is left because it is faster than <code>Enumerable#uniq?</code>.</p> Ruby master - Feature #16428: Add Array#uniq?, Enumerable#uniq?https://bugs.ruby-lang.org/issues/16428?journal_id=849842020-04-10T04:41:58Zmatz (Yukihiro Matsumoto)matz@ruby.or.jp
<ul><li><strong>Status</strong> changed from <i>Open</i> to <i>Feedback</i></li></ul><p>You said, "I often need to check if an array have duplicate elements". But we cannot think of the real-world use-case.<br>
Could you elaborate on how to use the proposed <code>#uniq?</code> and its benefit?</p>
<p>Matz.</p> Ruby master - Feature #16428: Add Array#uniq?, Enumerable#uniq?https://bugs.ruby-lang.org/issues/16428?journal_id=850172020-04-10T14:25:33Zkyanagi (Kouhei Yanagita)
<ul></ul><p>I was developing mobile games, and I met these situations:</p>
<p>A card deck can't have duplicate characters.<br>
i.e. <code>deck.cards.map(&:character_id).uniq.size == deck.cards.size</code><br>
-> <code>deck.cards.map(&:character_id).uniq?</code> or <code>deck.cards.uniq?(&:character_id)</code></p>
<p>When players compose items, each of them should be different.<br>
i.e. <code>materials.map(&:item_id).uniq.size == materials.size</code><br>
-> <code>materials.map(&:item_id).uniq?</code> or <code>materials.uniq?(&:item_id)</code></p>
<p>Another situation:</p>
<p>I developed a registration form for relay runners.<br>
A request body is like this:</p>
<pre><code># Missing sections are allowed. You can send them later.
[
{ section: 1, name: 'aaa' },
{ section: 3, name: 'bbb' },
{ section: 5, name: 'ccc' },
]
</code></pre>
<p>In this case, duplication of <code>section</code> is not allowed.<br>
<code>runners.map(&:section).uniq.size == runners.size</code><br>
-> <code>runners.map(&:section).uniq?</code> or <code>runners.uniq?(&:section)</code></p>
<p>I think <code>uniq?</code> is easier to write and read than <code>x.uniq.size == x.size</code><br>
for expression of no duplication. It's even faster.</p>
<p>This check is also found in Ruby's repository (bundler):<br>
<a href="https://github.com/ruby/ruby/blob/master/spec/bundler/support/matchers.rb#L84" class="external">https://github.com/ruby/ruby/blob/master/spec/bundler/support/matchers.rb#L84</a></p> Ruby master - Feature #16428: Add Array#uniq?, Enumerable#uniq?https://bugs.ruby-lang.org/issues/16428?journal_id=850182020-04-10T14:42:17Zshyouhei (Shyouhei Urabe)shyouhei@ruby-lang.org
<ul></ul><p>kyanagi (Kouhei Yanagita) wrote in <a href="#note-5">#note-5</a>:</p>
<blockquote>
<p>I was developing mobile games, and I met these situations:</p>
<p>A card deck can't have duplicate characters.<br>
i.e. <code>deck.cards.map(&:character_id).uniq.size == deck.cards.size</code><br>
-> <code>deck.cards.map(&:character_id).uniq?</code> or <code>deck.cards.uniq?(&:character_id)</code></p>
</blockquote>
<p>So you just want to test? Why doesn't <code>deck.cards.map(...).uniq!</code>'s return value work?</p>
<blockquote>
<p>When players compose items, each of them should be different.<br>
i.e. <code>materials.map(&:item_id).uniq.size == materials.size</code><br>
-> <code>materials.map(&:item_id).uniq?</code> or <code>materials.uniq?(&:item_id)</code></p>
</blockquote>
<p>So you just want to test? Don't you want to show the duplicated materials to the players? Does <code>uniq?</code> help then?</p>
<blockquote>
<p>Another situation:</p>
<p>I developed a registration form for relay runners.<br>
A request body is like this:</p>
<pre><code># Missing sections are allowed. You can send them later.
[
{ section: 1, name: 'aaa' },
{ section: 3, name: 'bbb' },
{ section: 5, name: 'ccc' },
]
</code></pre>
<p>In this case, duplication of <code>section</code> is not allowed.<br>
<code>runners.map(&:section).uniq.size == runners.size</code><br>
-> <code>runners.map(&:section).uniq?</code> or <code>runners.uniq?(&:section)</code></p>
</blockquote>
<p>So you just want to test? Don't you want to render error message about what is the duplicated section? Does <code>uniq?</code> help then?</p>
<blockquote>
<p>I think <code>uniq?</code> is easier to write and read than <code>x.uniq.size == x.size</code><br>
for expression of no duplication. It's even faster.</p>
</blockquote>
<p>My main question is: it isn't faster when you render error messages. How do you use it?</p>
<blockquote>
<p>This check is also found in Ruby's repository (bundler):<br>
<a href="https://github.com/ruby/ruby/blob/master/spec/bundler/support/matchers.rb#L84" class="external">https://github.com/ruby/ruby/blob/master/spec/bundler/support/matchers.rb#L84</a></p>
</blockquote>
<p>Honestlt I don't understand what this matcher is trying to achieve.</p> Ruby master - Feature #16428: Add Array#uniq?, Enumerable#uniq?https://bugs.ruby-lang.org/issues/16428?journal_id=850262020-04-10T16:06:38Zkyanagi (Kouhei Yanagita)
<ul></ul><p>In my cases, I (server side) only had to check duplication because a client also have validations.<br>
Legal users can't send a request with duplicates, so detailed error message was not required.<br>
(If needed, I could investigate logged request.)</p>
<p><code>uniq!</code>'s return value is also usable, but I think <code>uniq?</code> is more fitting.<br>
(I'd like to check duplication, not to get uniq array.)</p> Ruby master - Feature #16428: Add Array#uniq?, Enumerable#uniq?https://bugs.ruby-lang.org/issues/16428?journal_id=905422021-02-22T00:15:55Zkeithrbennett (Keith Bennett)keithrbennett@gmail.com
<ul></ul><p>I was just going to post this suggestion, but saw that it was already here.</p>
<p><code>uniq?</code> could be helpful, for example, where you are loading objects from an external source (e.g. from JSON or YAML), and you need to verify that the objects' id's are unique. <code>objects.map(&:id).uniq?</code> is much more expressive, clear, and concise, than the lower level, longer form that might be something like this:</p>
<pre><code>ids = objects.map(&:id)
ids.size == ids.uniq.size
</code></pre>
<p>Also, it's consistent with the style of existing methods like <code>empty?</code>, <code>one?</code>, etc.</p> Ruby master - Feature #16428: Add Array#uniq?, Enumerable#uniq?https://bugs.ruby-lang.org/issues/16428?journal_id=932812021-08-14T06:12:50Zgotoken (Kentaro Goto)gotoken@gmail.com
<ul></ul><p>Recently I read similar topic again elsewhere. They pointed</p>
<ul>
<li>in most cases we have something to do on each duplicate element if any duplicate detected, e.g., reporting all duplicate elements as an error message</li>
<li>
<code>uniq?</code> looks slightly odd because we don't have <code>sort?</code> or <code>clear?</code> (uniq etymology: Perl funtion uniq. Originally Version 3 Unix command uniq.)</li>
</ul>
<p>Though they make sense to me, but sometimes, in the case of back-of-the-envelope calculations, I just want to write code that just checks the array for duplicate elements, for example, to check whether a particular csv column meets a unique constraint from the irb console as Keith gave as an example.</p>
<p>So instead, I suggest a set of three methods</p>
<ul>
<li>
<code>#repeated</code> returns a new Array containing repeated elements. This may be what we need.</li>
<li>
<code>#repeated?</code> returns <code>true</code> if there is a repeated element. This may be faster than <code>! array.repeated.empty?</code> because can return <code>true</code> immediately when a repetition is detected.</li>
<li>
<code>#no_repeated?</code> returns the same to negation of <code>#repeated?</code>. This is what we want intuitively. And functionally identical to Kouhei's <code>uniq?</code>.</li>
</ul>
<p>Here I chose word <em>repeated</em> instead of <em>duplicate</em> so as not to confuse it with the meaning of <code>dup</code>.</p>