简体   繁体   English

我如何区分条件?

[英]How can I distinct with condition?

Here is class UserArrived :这是UserArrived类:

public class UserArrived{
   public string id{get;set;}
}

Here is class OldUser :这是OldUser类:

public class OldUser{
   public string id{get;set;}
   public DateTime lastArrived{get;set;}
}

And here is class User :这是类User

public class User{
   public string id{get;set;}
   public Boolean newUser{get;set;}
}

Finally, here is two List :最后,这里有两个List

List<UserArrived> UserArrivedList=new List<UserArrived>();
List<OldUser> OldUserList=new List<OldUser>();

All the id in each class is unique.每个类中的所有 id 都是唯一的。

Now I need to combine UserArrived and OldUser to a brand new List<User> .现在我需要将UserArrivedOldUser组合到一个全新的List<User>

As we know, the user arrives the shop may is a new user or an old user.我们知道,用户来到店铺可能是新用户,也可能是老用户。 If the user id in UserArrived also contains in OldUser , the property newUser in the new List is false for true.如果UserArrived的用户 ID 也包含在OldUser ,则新List的属性newUser为 false 为 true。

In my opinion, I will combine two List into one first and then use the distinct method to remove the duplicates.在我看来,我会先将两个 List 合并为一个,然后使用distinct方法去除重复项。

However, it seems the distinct can not run with a condition.但是,似乎distinct不能带条件运行。

Although I can use several foreach to solve this while I feel it is so troublesome.虽然我可以使用几个foreach来解决这个问题,但我觉得它很麻烦。 I want to use something easy just like lambda or linq .我想使用一些简单的东西,比如lambdalinq How can I achieve this?我怎样才能做到这一点?

============================= ==============================

Here is an example of the input:这是输入的示例:

List<UserArrived> UserArrivedList=new List<UserArrived>(){new UserArrived(){id="A"},new UserArrived(){id="B"},new UserArrived(){id="C"}};
List<OldUser> OldUserList=new List<OldUser>(){new OldUser(){id="B",lastArrived=DateTime.Now}};

the output is:输出是:

A,true
B,false
C,true

The thing about LINQ--it isn't always easy.关于 LINQ 的事情——并不总是那么容易。 In fact it can get quit cluttered.事实上,它可能会变得混乱。 In the question statement I read,在我读到的问题陈述中,

I want to use something easy just like lambda or linq.我想使用一些简单的东西,比如 lambda 或 linq。

Well, that is relative.嗯,那是相对的。 But, I think that when using LINQ, one should try to keep it simple.但是,我认为在使用 LINQ 时,应该尽量保持简单。 Even break the statement down into multiple statements if necessary.如有必要,甚至可以将语句分解为多个语句。 For that reason I propose this solution (demonstrated in a console app):出于这个原因,我提出了这个解决方案(在控制台应用程序中演示):

    static void Main(string[] args)
    {

        Console.WriteLine();
        Console.WriteLine("--------------------Test This Code -----------------------");

        var combined = TestUserCombined();

        //The following is just to demonstrate the list is populated properly
        combined.OrderBy(s => s.id.PadLeft(4, '0')).ToList().ForEach(k => Console.WriteLine($"X id: {k.id} | isNew:{k.newUser}"));
    }

    private static IEnumerable<User> TestUserCombined()
    {
        List<UserArrived> userArrivedList=new List<UserArrived>();
        List<OldUser> oldUserList=new List<OldUser>();

        //populate the lists...
        for(int i = 0; i < 20; i+=2)
        {
            var userArrived = new UserArrived();
            userArrived.id = i.ToString();
            userArrivedList.Add(userArrived);
        }

        for(int i = 0; i < 20; i+=3)
        {
            var oldUser = new OldUser();
            oldUser.id = i.ToString();
            oldUserList.Add(oldUser);
        }

        //Now for the solution...
        var selectedUserArrived = userArrivedList.Select(i => i.id);
        var selectedOldUser = oldUserList.Select(i => i.id);
        var users = selectedUserArrived
                             .Union(selectedOldUser)
                             .Select(j => new User{id=j,newUser=!(selectedUserArrived.Contains(j) && selectedOldUser.Contains(j))});
        return users;
    }


Certainly, this all could have been done in one statement, but I believe this makes it more readable and understandable.当然,这一切都可以在一个语句中完成,但我相信这使其更具可读性和可理解性。


EDIT:编辑:
There has been some discussion amongst the coders posting solutions as to exactly what conditions must be met in order for the value "newUser" to be set to "true".在发布解决方案的编码人员之间已经就必须满足哪些条件才能将值“newUser”设置为“true”进行了一些讨论。 It was my understanding from the initial posted question that the "id" must be present in both lists "UserArrivedList" AND "OldUserList", but I tend to agree with @JQSOFT that it makes more sense that the only condition that must be met should be that the "id" need only be present in "OldUserList".我从最初发布的问题中了解到,“id”必须出现在“UserArrivedList”和“OldUserList”这两个列表中,但我倾向于同意@JQSOFT,即必须满足的唯一条件应该更有意义是“id”只需要出现在“OldUserList”中。 If that is indeed the case than the Select() expression above should be .Select(j => new User{id=j,newUser=!selectedOldUser.Contains(j)});如果确实如此,那么上面的Select()表达式应该是.Select(j => new User{id=j,newUser=!selectedOldUser.Contains(j)});

If I understand your requirement you're saying that if an id is in both lists then the user is an old user, otherwise it is a new user.如果我理解您的要求,您会说如果两个列表中都有一个 id,则该用户是旧用户,否则是新用户。

So here's the simplest way that I could come up with to do it:所以这是我能想到的最简单的方法:

IEnumerable<User> users =
    Enumerable
        .Concat(
            UserArrivedList.Select(i => i.id),
            OldUserList.Select(i => i.id))
        .ToLookup(x => x)
        .Select(x => new User() { id = x.Key, newUser = x.Count() == 1 });

Let's test with some input:让我们用一些输入进行测试:

var UserArrivedList = new List<UserArrived>()
{
    new UserArrived() { id = "A" },
    new UserArrived() { id = "B" },
};

var OldUserList = new List<OldUser>()
{
    new OldUser() { id = "B" },
    new OldUser() { id = "C" },
};

Here are my results:这是我的结果:

用户

B is the only user who appears in both lists so should be False . B是唯一出现在两个列表中的用户,所以应该是False


So, there's a bit of confusion about the requirements here.所以,这里的要求有点混乱。

The OP has added a concrete example of the input data and the expected output. OP 添加了输入数据和预期输出的具体示例。

var UserArrivedList = new List<UserArrived>()
{
    new UserArrived() { id = "A" },
    new UserArrived() { id = "B" },
    new UserArrived() { id = "C" }
};

var OldUserList = new List<OldUser>()
{
    new OldUser() { id = "B", lastArrived = DateTime.Now }
};

With this input the OP is expecting True, False, True for A, B, C respectively.有了这个输入,OP 分别期望A, B, CTrue, False, True

Here is the code of the four current answers:这是当前四个答案的代码:

var results = new []
{
    new
    {
        answered = "Enigmativity",
        users = Enumerable
            .Concat(
                UserArrivedList.Select(i => i.id),
                OldUserList.Select(i => i.id))
            .ToLookup(x => x)
            .Select(x => new User() { id = x.Key, newUser = x.Count() == 1 })
    },
    new
    {
        answered = "JQSOFT",
        users = UserArrivedList.Select(x => x.id)
            .Concat(OldUserList.Select(y => y.id))
            .Distinct()
            .Select(x => new User
            {
                id = x,
                newUser = OldUserList.Count(o => o.id == x) == 0,
            })
    },
    new
    {
        answered = "Anu Viswan",
        users =
            UserArrivedList
                .Join(OldUserList, ual => ual.id, oul => oul.id, (ual, oul) => new User { id = oul.id, newUser = false })
                .Concat(UserArrivedList.Select(x => x.id).Except(OldUserList.Select(x => x.id))
                .Concat(OldUserList.Select(x => x.id).Except(UserArrivedList.Select(x => x.id)))
                .Select(x=> new User{ id = x, newUser = true}))
    },
    new
    {
        answered = "Barns",
        users =
            UserArrivedList.Select(i => i.id)
                .Union(OldUserList.Select(i => i.id))
                .Select(j => new User
                {
                    id = j,
                    newUser =
                        !(UserArrivedList.Select(i => i.id).Contains(j)
                            && OldUserList.Select(i => i.id).Contains(j))})
    }
};

That gives the output of:这给出了以下输出:

全部用户

So, currently all of the answers presented match the OP's example.因此,目前提供的所有答案都与 OP 的示例相匹配。

I'd be interested in the OP commenting on this as the input data:我对 OP 对此作为输入数据的评论很感兴趣:

    var UserArrivedList = new List<UserArrived>()
    {
        new UserArrived() { id = "A" },
        new UserArrived() { id = "B" },
    };

    var OldUserList = new List<OldUser>()
    {
        new OldUser() { id = "B" },
        new OldUser() { id = "C" },
    };

When I run this I get this output:当我运行它时,我得到这个输出:

替代输入

Here three users match and one does not.这里三个用户匹配,一个不匹配。

This all boils down to what the description means:这一切都归结为描述的含义:

As we know, the user arrives the shop may is a new user or an old user.我们知道,用户来到店铺可能是新用户,也可能是老用户。 If the user id in UserArrived also contains in OldUser, the property newUser in the new List is false for true.如果 UserArrived 中的用户 ID 也包含在 OldUser 中,则新 List 中的属性 newUser 为 false 为 true。

I hope I understood your query.我希望我理解你的询问。 One way to achieve this using Linq would be使用 Linq 实现这一目标的一种方法是

    var users = UserArrivedList.Join(OldUserList,ual=>ual.id,oul=>oul.id,(ual,oul)=>new User{id=oul.id,newUser=false})
                               .Concat(UserArrivedList.Select(x=>x.id).Except(OldUserList.Select(x=>x.id))
                               .Concat(OldUserList.Select(x=>x.id).Except(UserArrivedList.Select(x=>x.id)))
                               .Select(x=> new User{id=x,newUser=true}));

Now you need to create a distinct list of User type from two lists of different types;现在您需要从两个不同类型的列表中创建一个不同的User类型列表; UserArrived and OldUser objects. UserArrivedOldUser对象。 A user is identified by a unique id of string type.用户由字符串类型的唯一id

Accordingly, I'd suggest this:因此,我建议这样做:

var users = UserArrivedList.Select(x => x.id)
    .Concat(OldUserList.Select(y => y.id))
    .Distinct()
    .Select(x => new User
    {
        id = x,
        newUser = OldUserList.Count(o => o.id == x) == 0,
    }).ToList();

Which gets the unique ids from both UserArrivedList and OldUserList and creates new User object for each.它从UserArrivedListOldUserList获取唯一的 id,并为每个创建新的User对象。 The OldUserList.Count(o => o.id == x) == 0, assigns false to the newUser property if the user id exists in the OldUserList otherwise true . OldUserList.Count(o => o.id == x) == 0,如果用户id存在于OldUserList中, OldUserList false分配给newUser属性,否则为true

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM