0

私は現在、rubスクリプトを介してドロップダウンリスト内のアイテムの実行時の追加と削除を可能にするアプリを使用しています。Rubyはこんな感じ

SAFE = ;
return control if control.CyclesCount == 0;
control.Items.each{|item| control.Items.Remove(item) if item.Value.index('|').nil?};
return control;

コントロールはカスタムユーザーコントロールであり、そのアイテムはListItemCollctionです。Rubyコードを正しく取得するために単体テストを実行していて、問題が発生しています。私が渡しているListItemColletionは次のようになります。

var lic = new ListItemCOllection {
  new ListItem {Text = "Item2", Value = "8"}, 
  new ListItem {Text = "Item1", Value = "1"},
  new ListItem {Text = "Item3", Value = "3|1"},
  new ListItem {Text = "Item4", Value = "4"},
  new ListItem {Text = "Item5", Value = "5|2"},
  new ListItem {Text = "Item6", Value = "6"}
}

パイプを含む2つのアイテムを残す代わりに、このコードは常にアイテムコレクションに3つのアイテムを残すように見えます。3は、アイテムを入れた順序によって異なります(この順序では、Item1、Item3、Item5が残ります)。これにより、削除が台無しになっていると思います。また、コレクションのコピーを取り、それをループして、元のコレクションから削除して、繰り返し処理していたコレクションから削除しないようにしました。私はRubyに関係のある初心者なので、気楽にやってください...しかし、いくつかのアドバイスを使うことができます。

ありがとう

4

3 に答える 3

5

反復中に配列を変更することはお勧めできません。配列を変更することを目的としたイテレータがいくつかあります。

a= [1,2,3]
b= [1,2,3]
a.delete_if { |x| x == 2 } # => [1,3]
b.reject! { |x| x == 2 } # => [1,3]
a # => [1,3]
b # => [1,3]

Array#delete_if配列の要素を削除します。とのわずかな違いがありますArray#reject

a= [1,2,3]
b= [1,2,3]
a.delete_if { |x| false } # => [1,3]
b.reject! { |x| false } # => nil
a # => [1,2,3]
b # => [1,2,3]

Array#delete_if常に残りの配列を返します。Array#reject!配列が変更されない場合は、代わりにnilを返します。

元の配列を変更しない、さらにいくつかのmodifiiengイテレータ:

a= [1,2,3]
a.reject { |x| x == 2 } # => [1,3]
a # => [1,2,3]

Array#reject拒否された要素のない配列を返しますが、元の配列は変更しません。

a= [1,2,3]
a.select { |x| x != 2 } # => [1,2,3]
a # => [1,3]

Array#select選択した要素のみの配列を返しますが、元の配列は変更しません。

于 2010-02-16T00:21:54.727 に答える
3

コレクションを反復処理しているときにコレクション変更することは、決して良い考えではありません。そうすれば、すべての地獄が解き放たれます。(できれば、ある種の例外が発生しますが、それが人生です...)

ただし、これは実際にはコードの最大の問題ではありません。最大の問題は、Rubyの大罪を犯したことです。知らないことEnumerableです。(心配しないでください:誰もがその罪を犯します。常に。)

条件を満たすコレクションのすべての要素を拒否する場合は、そのためのメソッドがあり、期待どおりに呼び出されますEnumerable#reject!

では、これを片付けましょう。

SAFE = ;

そのセミコロンはそこで何をしているのですか?あなたはC#とRubyを混同しているようです:-)(ああ、そしてまた、その行はとにかく何の役にも立ちませんよね?)

return control if control.CyclesCount == 0;

繰り返しますが、役に立たないセミコロンです。

control.Items.each{|item| control.Items.Remove(item) if item.Value.index('|').nil?};

これはそれが面白くなるところです:

control.Items.reject! {|item| item.Value.include?('|') }

はるかに良いですね。

return control;

私は個人的returnに「純粋な」メソッド(つまり、副作用のないメソッド)のキーワードを予約したいので、コードが変更されるため、ここでは使用しませんが、これcontrol.Itemsはスタイルの選択です。すべてをまとめると、これが私がそれを書く方法です:

return control if control.cycles_count == 0
control.items.reject! {|item| item.value.include?('|') }
control

注:現在、IronRubyのインストールが機能していないため、残念ながらテストできないと仮定しています。

  • メソッド名の音訳(CyclesCount-> cycles_count)は機能しますが、
  • Valueある種のStringまたはコレクションであり、
  • ListItemCollectionミックスインEnumerable

実装する場合は後者が当てはまるはずです(そうでない場合は、IronRubyのバグだと思います)。が実装されていない場合(おそらくバグと見なされます)、それでも簡単に修正できます。ListItemCollectionIEnumerableListItemCollectionIEnumerableListItemCollection

class ListItemCollection; include Enumerable end

[ところで:テストを取り除くことができるように、cycles?メソッド(またはbool HasCycles.NET側のプロパティ)も紹介しますcycle_count == 0。]

于 2010-02-16T00:37:39.093 に答える
1

条件に基づいて配列からアイテムを削除するだけの場合は、次を使用する必要がありますArray#reject!

control.Items.reject! {|item| item.Value.index('|').nil? };

ただし、これを適切にデバッグするにはcontrol.Items、Ruby側でどのように見えるかを知る必要があります。

于 2010-02-16T00:21:33.120 に答える