c#基于另一个数组的数组排序部分



我有一个表示用户的类数组和另一个表示固定项(目前只有用户id)的类数组。下面是这些类:

public class User
{
public int UserId { get; set; }
public bool Pinned { get; set; }
public User(int userId, bool pinned)
{
UserId = userId;
Pinned = pinned;
}
}
public class PinnedItem
{
public int UserId { get; set; }
public PinnedItem(int userId)
{
UserId = userId;
}
}

所有被钉住用户的用户id都按照特定的顺序保存(被钉住的项目的顺序),我想对用户数组进行排序,使被钉住的用户在顶部,被钉住的用户遵循被钉住的项目数组的顺序。例如,如果我有一个用户数组,如

var users = new []{ new User(1, true), new User(2, false), new User(3, true) }

和一个固定项数组,如下所示:

var pinnedItems = new [] { new PinnedItem(3), new PinnedItem(1) }

那么我希望生成的数组是这样的:

[ {3, true}, {1, true}, {2, false} ]

我也需要它的工作,如果固定项的数组不是在任何类型的顺序。如果我有这个用户数组:

var users = new []{ new User(1, false), new User(2, true), new User(3, true), new User(4, true) }

和这个固定项数组:

var pinnedItems = new [] { new PinnedItem(3), new PinnedItem(2), new PinnedItem(4) }

在本例中,我希望结果数组看起来像这样:

[ {3, true}, {2, true}, {4, true}, {1, false} ]

任何形式的帮助将是非常感激的。此外,如果问题中有不清楚的地方,我很抱歉,如果需要的话,我会相应地修改。

这有点邋遢,但是像这样的东西可以做到:

var joined = 
users
.GroupJoin(pinnedItems, u => u.UserId, p => p.UserId, (u, p) => new { u.UserId, Pinned = p.Any() })
.OrderByDescending(r => r.Pinned)
.ThenByDescending(r => r.UserId)
.ToList();

您可以调整投影和排序以获得您想要的结果。

我相信有很多方法可以做到这一点,我还有很多LINQ要学习,但下面的应该让你开始;

// First, get the users that are mentioned by a PinnedItem 
var pinnedUsers = pinnedItems.Select(x => users.FirstOrDefault(y => y.UserId == x.UserId));
// Get all the users that are not mentioned in a PinnedItem
var unpinnedUsers = users.Except(pinnedUsers);
// Combine both
var both = pinnedUsers.Concat(unpinnedUsers);

如果有人偶然发现这篇文章,我的导师提出了一个针对更大数组优化的解决方案(如果你知道不会有很多固定项目,@Fixation发布的答案是完全好的):

Dictionary<int, int?> positionByUserId = pinnedItems
.Select((i, index) => new { i.UserId, Position = index })
.ToDictionary(x => x.UserId, x => (int?)x.Position);
var result = users
.Select(u => new
{
User = u,
Position = positionByUserId.GetValueOrDefault(u.UserId) ?? int.MaxValue
})
.OrderBy(x => x.Position)
.Select(x => x.User)
.ToArray();

最新更新