根据对象与另一个对象的比较,对对象列表进行排序

时间:2011-12-10 00:26:55

标签: c# asp.net-mvc-3

这是我的用户对象:

public class User
{
    public int UserId { get; set; }
    public string Name { get; set; }
    public virtual ICollection<Tag> Tags { get; set; }
}

在我的控制器中,我根据用户ID选择当前登录的用户:

User CurrentUser = Db.Users.Find((int)Session["UserId"]);

接下来,我选择除当前登录用户之外的所有用户的列表:

List<User> Users = Db.Users.Where(u => u.UserId != CurrentUser.UserId).ToList();

这里真的让人感到困惑:我想根据他们的标签列表与当前登录用户的标签列表的比较程度来对这个用户列表进行排序。例如,假设用户A(当前已登录)具有以下标记列表:

List<Tag> CurrentUserTags = new List<Tag>
{
    new Tag
    {
        TagId = 1
    },
    new Tag
    {
        TagId = 2
    },
    new Tag
    {
        TagId = 3
    }
}

用户B有标签1和2.用户C只有标签1.我想按如下方式对用户列表进行排序:用户B然后是用户C,因为用户B的标签列表与用户A的标签列表进行了更密切的比较比用户C的列表。

我真的希望这是有道理的,因为我完全陷入困境。

3 个答案:

答案 0 :(得分:2)

使用标记中的标识创建哈希集:

var currentTags = new HashSet<int>(CurrentUserTags.Select(t => t.TagId));

然后,您可以计算哈希集中存在的标记:

Users = Users.OrderByDescending(
  u => u.Tags.Count(t => currentTags.Contains(t.TagId))
).ToList();

答案 1 :(得分:2)

首先使用Intersect

Users.OrderBy(o => o.Tags.Intersect(CurrentUser.Tags).Count)

现在这不会起作用,因为它会比较对Tag对象的引用,你想要ID。

您可以选择实现自定义相等运算符或IEqualityComparer<T>并传递它。

public class TagComparer : IEqualityComparer<Tag>
{
    public bool Equals(Tag a, Tag b)
    {
        return a.TagId == b.TagId;
    }
}

Users.OrderBy(o => o.Tags.Intersect(CurrentUser.Tags, new TagComparer()).Count)

答案 2 :(得分:0)

按标准排序List时,我通常会实现IComparer接口。

public class CompareUser : IComparer<User>
{
    public User o;

    public CompareUser(User p)
    {
        o = p;
    }

    public int Compare(User o1, User o2)
    {
        return (o1.Tags.Intersect(o.Tags).Count() < o2.Tags.Intersect(o.Tags).Count()) ?
            1 : -1;            
    }
}

然后使用此Comparer对List进行排序。

CompareUser c = new CompareUser(CurrentUser);
Users.sort(c);

HTH。