1

解決策を探しましたが、よくわかりません。linq はこれをきちんと処理できるはずだと思いますが、私は linq クエリを作成するのが得意ではありません。基本的に私はクラスを持っています。

public class Message
{
    public int CreatedByPersonID { get; set; }
    public int? PostedToPersonID { get; set; }
}

私が探しているのは、次の linq の等価物です。

List<int> personIDs = new List<int>();
foreach (Message message in messages)
{
    if (!personIDs.Contains(message.CreatedByPersonID))
    {
        personIDs.Add(message.CreatedByPersonID);
    }
    if (message.PostedToPersonID != null && !personIDs.Contains(message.PostedToPersonID.Value))
    {
        personIDs.Add(message.PostedToPersonID.Value);
    }
}

これのlinqバージョンはありますかそれとも技術に期待しすぎなのか…?のいくつかのバージョンを探していることはわかっていますが、複数のフィールドを持つSelect()を作成する方法がわかりませんdistinct

4

1 に答える 1

3
List<int> personIDs = 
     messages.SelectMany(m => m.PostedToPersonID.HasValue ?
                  new int[] { m.PostedToPersonID.Value, m.CreatedByPersonID } :
                  new int[] { m.CreatedByPersonID })
             .Distinct()
             .ToList();

別のオプションは、2 回列挙することです。

List<int> personIDs =
    messages.Where(m => m.PostedToPersonID.HasValue)
            .Select(m => m.PostedToPersonID.Value)
            .Concat(messages.Select(m => m.CreatedByPersonID))
            .Distinct()
            .ToList();

しかし、おそらく Linq がなければ、より読みやすく高速なコードが得られます

public IEnumerable<int> GetAllPersonIdsFrom(IEnumerable<Message> messages)
{
     foreach(var message in messages)
     {
         yield return message.CreatedByPersonID;

         if (message.PostedToPersonID.HasValue)
             yield return message.PostedToPersonID.Value;
     }
}

もう1つの解決策 - 個別の値を持つ単一の列挙

public static List<int> GetDistinctPersonIdsFrom(IEnumerable<Message> messages)
{
    HashSet<int> ids = new HashSet<int>();

    foreach (var message in messages)
    {
        ids.Add(message.CreatedByPersonID);
        if (message.PostedToPersonID.HasValue)
            ids.Add(message.PostedToPersonID.Value);
    }

    return ids.ToList();
}
于 2013-02-22T10:36:30.717 に答える