2

私はこのような関数を書きました

let GetAllDirectAssignmentsforLists (spWeb : SPWeb) =    
  spWeb.Lists 
  |> Seq.cast<SPList> 
  |> Seq.filter(fun l -> l.HasUniqueRoleAssignments) 
  |> Seq.collect (fun l -> l.RoleAssignments 
                           |> Seq.cast<SPRoleAssignment> 
                           |> Seq.map(fun ra -> ra.Member)
                 )
  |> Seq.filter (fun p -> p.GetType().Name = "SPUser")
  |> Seq.map(fun m -> m.LoginName.ToLower())

l.Title送信パイプと。にリスト名(から取得)を含むタプルを返したいm.LoginName.ToLower()

上記のパイプ要素から何かを取得するためのクリーンウェイはありますか?

もちろん、1つの方法は、パイプの2番目のステージで戻り値をタプルしてから、タイトルを最後まで渡すことです。しかし、それはコードを汚染し、後続のすべてのステージは、タプル値を受け入れて返す必要があります。価値を得るための最終段階のために。

クリーンで簡単な方法があるのだろうか…。

また、パイプラインのステージ4で、(fun p -> p.GetType().Name = "SPUser")ここでタイプを比較する場合に使用できますか?typename文字列に変換してからstring一致させるのではなく?

4

2 に答える 2

4

Seq.filter結果を変更せずに、を内部にSeq.mapプッシュできるという事実を利用しSeq.collectます。この場合、lは引き続きアクセスできます。

そして最後の関数は、型テスト演算子filterで使用するのがより慣用的です。 :?

let GetAllDirectAssignmentsforLists(spWeb: SPWeb) =    
    spWeb.Lists 
    |> Seq.cast<SPList> 
    |> Seq.filter (fun l -> l.HasUniqueRoleAssignments) 
    |> Seq.collect (fun l -> l.RoleAssignments 
                             |> Seq.cast<SPRoleAssignment> 
                             |> Seq.map (fun ra -> ra.Member)
                             |> Seq.filter (fun p -> match box p with
                                                     | :? SPUser -> true
                                                     | _ -> false)
                             |> Seq.map (fun m -> l.Title, m.LoginName.ToLower()))

さらに単純化するために、一連のSeq.mapSeq.filterSeq.chooseに変更できます。

Seq.choose (fun ra -> match box ra.Member with
                      | :? SPUser -> Some (l.Title, ra.Member.LoginName.ToLower())
                      | _ -> None)
于 2012-09-26T09:06:19.100 に答える
3

残りの計算を内部で持ち上げることで問題を解決できますが、パイプラインの代わりにシーケンス式collectを使用することで、コードを読みやすくすることができると思います。

コードを実行してテストすることはできませんでしたが、これは同等である必要があります。

let GetAllDirectAssignmentsforLists (spWeb : SPWeb) = seq {
  // Corresponds to your 'filter' and 'collect'
  for l in Seq.cast<SPList> spWeb.Lists do
    if l.HasUniqueRoleAssignments then
      // Corresponds to nested 'map' and 'filter'
      for ra in Seq.cast<SPRoleAssignment> l.RoleAssignments do
        let m = ra.Member
        if m.GetType().Name = "SPUser" then 
          // This implements the last 'map' operation
          yield l.Title, m.LoginName.ToLower() }

上記のコードは、元のコードよりも@padによるバージョンに密接に対応しています。これは、残りの計算が下にネストされているためfor(これは、下にネストされていることに対応しますcollect)、すでにスコープ内にあるすべての変数を確認できるためですl。必要。

ifシーケンス式の良いところは、(の代わりにfilter)、for(の代わりに)などのF#構造体を使用できることですcollect。また、ネストされた操作(変数をスコープ内に保持するためにここで必要)を記述するのに適していると思います。非常に読みやすく、使い慣れたコード構造を維持します。

于 2012-09-26T12:42:58.313 に答える