【问题标题】:find list elements which are similar to other list elements by 3 properties and then add value from the second one to the first通过 3 个属性查找与其他列表元素相似的列表元素,然后将第二个元素的值添加到第一个元素
【发布时间】:2017-10-15 07:15:14
【问题描述】:
protected void AddPositionForPlayers(List<Player> players,
                                     List<Player> playerPosition)
{
    foreach (Player player in players)
    {
        foreach (Player playerPos in playerPosition)
        {
            if (player.FirstName == playerPos.FirstName &&
                player.LastName == playerPos.FirstName &&
                player.TeamName == playerPos.TeamName)
            {
                player.Position = playerPos.Position;
            }
        }
    }
}

我应该如何将此函数更改为 LINQ?或者它是不应该用 LINQ 完成的事情之一?因为找不到类似这个问题的东西..

【问题讨论】:

  • 您希望在此处使用 LINQ 获得什么好处?
  • 您是要从第二个开始添加每个位置(即+=)还是将第二个位置分配给第一个?
  • 大学项目要求之一就是尽可能多地使用LINQ。所以我改变了排序算法,最有价值球员的选择,现在正在考虑这个功能,或者是否有可能并且值得改变它。
  • KMoussa,只需将第二个的位置分配给第一个。

标签: c# list linq object


【解决方案1】:

如果您的列表长度相等,并且您希望在 3 个匹配属性时将第二个列表元素的值添加到第一个列表元素,那么以下代码将实现:

List<Player> players = players.Zip(playerPosition, (player, playerPosition) => (
    if (player.FirstName == playerPos.FirstName &&
        player.LastName == playerPos.FirstName &&
        player.TeamName == playerPos.TeamName) {
            player.Position = playerPos.Position;
        }

));

您的代码看起来很奇怪,因为如果 playerPosition 中有超过 1 个元素匹配 3 个属性,那么 player.position 元素将设置为 playerPosition 中的最后一个匹配元素。

【讨论】:

    【解决方案2】:

    好吧,我看不出它有什么好处,但你可以将List&lt;T&gt;.ForEachFirstOrDefaultnull-conditional operator 结合使用:

    protected void AddPositionForPlayers(List<Player> players, List<Player> playerPosition)
    {
        players
            .ForEach(p => p.Position = 
                playerPosition.FirstOrDefault(pp => 
                   p.FirstName == pp.FirstName && p.LastName == pp.LastName && p.TeamName == pp.TeamName)
                ?.Position);
    }
    

    但是我可能会考虑实现EqualsGetHashCode 以在查询player1 == player2 中使用简单的相等运算符。我还会考虑是否应该使用Dictionary&lt;TKey, TValue&gt;HashSet&lt;T&gt; 集合进行快速查找。

    附言

    如果它们总是具有相同的顺序和长度,我可能会使用一个简单的for 循环来代替:

    for(var i = 0; i < players.Length; i++)
    {
        if(players[i].FirstName == playerPosition[i].FirstName && players[i].LastName == playerPosition[i].LastName && players[i].TeamName == playerPosition[i].TeamName)
        {
             players[i].Position = playerPosition[i].Position;
        }
    }
    

    使用 LINQ 解决方案也会有所不同(仅供参考,我建议使用此代码):

            players
                .Where((p, i) =>
                    {
                        Player pp = playerPosition[i];
                        bool result = p.FirstName == pp.FirstName && p.LastName == pp.LastName && p.TeamName == pp.TeamName;
                        if (result)
                        {
                            p.Position = pp.Position;
                        }
                        return result;
                    }).ToList();  // note that this will create a copy of players List
    

    【讨论】:

      【解决方案3】:

      您可以加入它们并循环连接结果以更新列表:

      var joined = players.Join(
          playerPosition,
          p => new {p.FirstName, p.LastName, p.TeamName},
          p => new {p.FirstName, p.LastName, p.TeamName},
          (player, playerPos) => new {player, playerPos});
      foreach (var pair in joined) pair.player.Position = pair.playerPos.Position;
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2013-09-25
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多