交叉操作在逗号分隔的字符串列表上

时间:2013-07-20 10:58:10

标签: c#

我有一个逗号分隔的字符串列表,如下所示:

    List<string> IdList=new List<string>();

并且列表的每个元素都有逗号分隔的字符串,如

     1,2,4,5,6,7,8,10,12,15,16
     2,3,5,7,8,9,0,10,16,17
     4,5,89,12,13,1,2,3,6,7,10,16

我想在这个字符串列表中应用AND操作,所以我得到如下输出:

      2,5,7,10,16

有没有有效的方法来实施交叉口操作?

3 个答案:

答案 0 :(得分:4)

您实际上正在寻找交叉点

如果您不需要按数字顺序排列值,则可以将每个字符串视为逗号分隔值。从第一个列表开始,然后恰当地相互交叉:

HashSet<string> set = new HashSet<string>(list[0].Split(','));
foreach (var item in list.Skip(1))
{
    set.IntersectWith(item.Split(','));
}
string result = string.Join(",", set);

完整的示例代码:

using System;
using System.Collections.Generic;
using System.Linq;

class Test
{
    static void Main()
    {
        var list = new List<string>
        {
            "1,2,4,5,6,7,8,10,12,15,16", 
            "2,3,5,7,8,9,0,10,16,17",
            "4,5,89,12,13,1,2,3,6,7,10,16"
        };

        HashSet<string> set = new HashSet<string>(list[0].Split(','));
        foreach (var item in list.Skip(1))
        {
            set.IntersectWith(item.Split(','));
        }
        string result = string.Join(",", set);
        Console.WriteLine(result);
    }
}

结果(订单无法保证):

2,5,7,10,16

答案 1 :(得分:2)

我不知道“内存利用率较低”,但我对此的第一次尝试将是这些内容(未经测试,在浏览器中编码,没有Visual Studio方便的yadda yadda):

Dictionary<int,int> occurences = new Dictionary<int,int>();
int numberOfLists = YourCollectionOfOuterLists.Count;

foreach (string list in YourCollectionOfOuterLists) {
    foreach (string value in list.Split(',')) {
        occurences[value] = ((occurences[value] as int) ?? 0) + 1;
    }
}

List<int> output = new List<int>();
foreach (int key in occurences.Keys) {
    if (occurences[key] == numberOfLists) {
        output.Add(key);
    }
}

return String.Join(output.Select(x => x.ToString()), ",");

很可能更简洁地编写代码,但是任何完成你所看到的东西的东西仍然必须执行大致相同的步骤:确定所有列表中存在哪些元素(这有点不重要)由于列表数量未知),然后从这些值中创建一个新列表。

如果您有权访问它,Parallel.ForEach()之类的内容可能有助于减少至少第二个循环的挂钟执行时间(可能是第一个循环,并且正确锁定/同步到位)。

如果您正在接受除此之外的其他事情,请澄清您的问题以准确描述您想要的内容。

答案 2 :(得分:0)

我不确定效果,但您可以使用Aggregate扩展方法来“折叠交叉点”。

var data = new List<string>
{
    "1,2,4,5,6,7,8,10,12,15,16",
    "2,3,5,7,8,9,0,10,16,17",
    "4,5,89,12,13,1,2,3,6,7,10,16",
};

var fold = data.Aggregate(data[0].Split(',').AsEnumerable(), (d1, d2) => d1.Intersect(d2.Split(',')));