3

我有一个名为对话的表格,其中列出了同一对话中的用户。例如:

id | conversation | user
1  |  1           |  Bob
2  |  1           |  Jane
3  |  2           |  Tim
4  |  2           |  Lily
5  |  2           |  Rick

而且我的列表中有一些这样的用户..

List<string> usernames = new List<string>{"Bob","Jane"};

我现在想检查用户何时想要与其他用户开始对话,他们之前是否曾与其他用户进行过对话(排他性的)。

例如。Bob 想与 Jane 创建一个新对话。(我的用户名 List 值中有 Bob 和 Jane 来比较他们之前是否进行过对话?)

正如我们看到他们两个已经进行了对话,我想获得属于这两个人的对话 ID。

如果我的列表包含以下数据,像这样..

List<string> usernames = new List<string>{"Bob","Jane","Tim"};

这次我期待之前的那三个没有对话。

我想知道没有我可以为他们创建一个新的对话。

我已经用 Linq 尝试过这个,但到目前为止还没有得到任何正确的结果。

提前感谢您的帮助;

4

5 回答 5

2

您可以按对话 ID 分组,并将组与您的用户列表匹配:

var previousConversations = userConversations
    .GroupBy(uc => uc.Conversation)
    .Where(g => g.OrderBy(uc => uc.user).Select(uc => uc.user)
        .SequenceEqual(usernames.Sort()));
于 2013-10-08T09:11:36.643 回答
1

您可以使用 SequenceEqual 方法来比较 2 个序列。

var users1 = new List<String> { "Bob", "Jane" };
var users2 = new List<String> { "Bob", "Jane", "Tim" };
var tableData = new List<YourTable>
    {
        new YourTable {foreignKey = 1, name = "Bob"},
        new YourTable {foreignKey = 1, name = "Jane"},
        new YourTable {foreignKey = 2, name = "Tim"},
        new YourTable {foreignKey = 2, name = "Lily"},
        new YourTable {foreignKey = 2, name = "Rick"},
    };
var keyFound = (from t in tableData
                group t by t.foreignKey into users
                where users.Select(u => u.name).SequenceEqual(users1)
                select users.Key).FirstOrDefault();

var keyNull = (from t in tableData
               group t by t.foreignKey into users
               where users.Select(u => u.name).SequenceEqual(users2)
               select users.Key).FirstOrDefault();

编辑:您使用 linq 作为从数据库中获取数据的一种方式,并非所有操作都支持这种方式。我们可以做的是提取内存中的选择,然后我们可以再次使用所有操作。
根据您的情况,这可能不是一个好主意,通常您希望让 sql 处理所有查询能力,因为他更擅长于此。
但是,如果您在一张不太大的桌子上选择,您可以轻松地拉入内存,随意这样做:

var rawData = (from t in tableData
               group t by t.foreignKey into users
               select users).ToList();

var key = (from d in rawData
           where d.Select(u => u.name).SequenceEqual(users2)
           select d.Key).FirstOrDefault();

另一方面,如果数据太大并且您希望它在 sql 端执行,我会考虑为此创建一个存储过程。

于 2013-10-08T09:19:03.467 回答
0

检查以下 linq。如果任何对话为空(枚举不产生结果),它将导致对话 id。您可以相应地检查您的条件。

var cust = new List<Table>
                       {
                           new Table {Conversation = 1, Id = 1, User = "Bob"},
                           new Table {Conversation = 1, Id = 2, User = "Jane"},
                           new Table {Conversation = 2, Id = 3, User = "Tim"},
                           new Table {Conversation = 2, Id = 4, User = "Lily"},
                           new Table {Conversation = 2, Id = 5, User = "Rick"}
                       };
        var names = new List<string> { "Rick", "Lily", "Tim" };


        var res = from x in cust
                  group x by x.Conversation
                  into y
                  where y.Select(z => z.User).Intersect(names).Count() == names.Count
                  select y.Key;
于 2013-10-09T05:23:30.397 回答
0

感谢大家的帮助和回答。下面的代码起到了作用,并给了我想要的结果。感谢 Kristof 提供此代码和您的努力。我在第二个查询中附加了 order by 子句,否则它不会给出正确的结果。希望这可以帮助需要类似东西的人。

var users1 = new List<String> { "Bob", "Jane" };
var users2 = new List<String> { "Bob", "Jane", "Tim" };

var tableData = new List<YourTable>
    {
        new YourTable {foreignKey = 1, name = "Bob"},
        new YourTable {foreignKey = 1, name = "Jane"},
        new YourTable {foreignKey = 2, name = "Tim"},
        new YourTable {foreignKey = 2, name = "Lily"},
        new YourTable {foreignKey = 2, name = "Rick"},
    };



var rawData = (from t in tableData
               group t by t.foreignKey into users
               select users).ToList();

var key = (from d in rawData
           where d.Select(u => u.name).OrderBy(s=> s).SequenceEqual(users2.OrderBy(s=>s))
           select d.Key).FirstOrDefault();
于 2013-10-09T09:59:15.573 回答
0

你基本上是在做一个“这些标签”的查询,在这里得到了回答:

搜索多个标签时按标签选择项目

应用于您的问题,它看起来像:

int userCount = myUsers.Count;

List<int> conversationIds = conversationsUsers
  .Where(cu => myUsers.Contains(cu.UserName))
  .GroupBy(cu => cu.ConversationId)
  .Where(g => g.Select(cu => cu.Username).Distinct().Count() == userCount)
  .Select(g => g.Key)

(只)。

好吧,好吧...将用户过滤移到组过滤中。

int userCount = myUsers.Count;

List<int> conversationIds = conversationsUsers
  .GroupBy(cu => cu.ConversationId)
  .Where(g => g.Select(cu => cu.Username).Distinct().Count() == userCount)
  .Where(g => g.Select(cu => cu.UserName).All(userName => myUsers.Contains(userName)))
  .Select(g => g.Key)
于 2013-10-08T12:27:06.970 回答