Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/linq/3.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 从元组列表中删除重复项_C#_Linq - Fatal编程技术网

C# 从元组列表中删除重复项

C# 从元组列表中删除重复项,c#,linq,C#,Linq,我有一个元组对象列表,我想删除重复项,例如,元组(a,b)和(b,a)被认为是相同的(这些是图形的边)。做这件事的好方法是什么?您可能需要创建一个实现IEqualityComparer的类: 尝试使用字典并编一个表示每个元组的键。您是否有一个不会出现在字符串中的字符,可以用作分隔符?在本例中,我选择了“:”: static void Main(string[] args) { // original list of data var list = new List<Tupl

我有一个
元组
对象列表,我想删除重复项,例如,元组
(a,b)
(b,a)
被认为是相同的(这些是图形的边)。做这件事的好方法是什么?

您可能需要创建一个实现
IEqualityComparer
的类:


尝试使用字典并编一个表示每个元组的键。您是否有一个不会出现在字符串中的字符,可以用作分隔符?在本例中,我选择了“:”:

static void Main(string[] args)
{
    // original list of data
    var list = new List<Tuple<string, string>> { };
    list.Add(new Tuple<string, string>("a", "b"));
    list.Add(new Tuple<string, string>("b", "a"));

    // dictionary to hold unique tuples
    var dict = new Dictionary<string, Tuple<string, string>>();
    foreach (var item in list)
    {
        var key1 = string.Concat(item.Item1, ":", item.Item2);
        var key2 = string.Concat(item.Item2, ":", item.Item1);

        // if dict doesnt contain tuple, add it.
        if (!dict.ContainsKey(key1) && !dict.ContainsKey(key2))
            dict.Add(key1, item);
    }

    // print unique tuples
    foreach (var item in dict)
    {
        var tuple = item.Value;
        Console.WriteLine(string.Concat(tuple.Item1, ":", tuple.Item2));
    }

    Console.ReadKey();
}
static void Main(字符串[]args)
{
//原始数据列表
var list=新列表{};
添加(新元组(“a”、“b”);
添加(新元组(“b”、“a”);
//保存唯一元组的字典
var dict=新字典();
foreach(列表中的变量项)
{
var key1=string.Concat(item.Item1,“:”,item.Item2);
var key2=string.Concat(item.Item2,“:”,item.Item1);
//如果dict不包含元组,则添加它。
如果(!dict.ContainsKey(键1)和&!dict.ContainsKey(键2))
添加指令(键1,项目);
}
//打印唯一元组
foreach(dict中的var项目)
{
var tuple=item.Value;
WriteLine(string.Concat(tuple.Item1,“:”,tuple.Item2));
}
Console.ReadKey();
}

您需要创建一个比较器,该比较器可以比较元组,从而使项的顺序无关紧要:

public class UnorderedTupleComparer<T> : IEqualityComparer<Tuple<T, T>>
{
    private IEqualityComparer<T> comparer;
    public UnorderedTupleComparer(IEqualityComparer<T> comparer = null)
    {
        this.comparer = comparer ?? EqualityComparer<T>.Default;
    }

    public bool Equals(Tuple<T, T> x, Tuple<T, T> y)
    {
        return comparer.Equals(x.Item1, y.Item1) && comparer.Equals(x.Item2, y.Item2) ||
                comparer.Equals(x.Item1, y.Item2) && comparer.Equals(x.Item1, y.Item2);
    }

    public int GetHashCode(Tuple<T, T> obj)
    {
        return comparer.GetHashCode(obj.Item1) ^ comparer.GetHashCode(obj.Item2);
    }
}
实时代码:

首先对元组对进行排序,然后执行不同的操作:

using System;
using System.Collections.Generic;

using System.Linq;

public class Program
{
    static List<Tuple<string, string>> myList = new List<Tuple<string, string>>()
    {
        Tuple.Create<string, string>("A", "B"),
        Tuple.Create<string, string>("B", "A"), // duplicate
        Tuple.Create<string, string>("C", "B"),
        Tuple.Create<string, string>("C", "B"), // duplicate
        Tuple.Create<string, string>("A", "D")              
    };

    public static void Main()
    {
        myList
            .Select(x => new[] { x.Item1, x.Item2 }.OrderBy(s => s).ToArray())
            .Select(x => Tuple.Create<string,string>(x[0], x[1]))
            .Distinct()
            .Dump();
    }
}
使用系统;
使用System.Collections.Generic;
使用System.Linq;
公共课程
{
静态列表myList=新列表()
{
Tuple.Create(“A”、“B”),
Tuple.Create(“B”,“A”),//重复
Tuple.Create(“C”、“B”),
Tuple.Create(“C”,“B”),//重复
Tuple.Create(“A”、“D”)
};
公共静态void Main()
{
迈利斯特
.Select(x=>new[]{x.Item1,x.Item2}.OrderBy(s=>s.ToArray())
.Select(x=>Tuple.Create(x[0],x[1]))
.Distinct()
.Dump();
}
}
输出:

Dumping object(System.Linq.<DistinctIterator>d__81`1[Tuple`2[String,String]])
[
   {
   Item1  : A
   Item2  : B
   ToString(): (A, B)
   },
   {
   Item1  : B
   Item2  : C
   ToString(): (B, C)
   },
   {
   Item1  : A
   Item2  : D
   ToString(): (A, D)
   }
]
Pair: B A
Pair: C B
Pair: A D
Pair: E F
转储对象(System.Linq.d_u81`1[Tuple`2[String,String]]
[
{
项目1:A
项目2:B
ToString():(A,B)
},
{
项目1:B
项目2:C
ToString():(B,C)
},
{
项目1:A
项目2:D
ToString():(A,D)
}
]

要保留原始内容,请使用,而不是,这样我们仍然可以访问组的第一个元素:

实时代码:


使用EqualityComparer不起作用吗,如本文所示,您是否需要保留元组的顺序,例如,您是否可以对它们进行排序,以便首先不必考虑顺序。解决方案几乎是列出反向元组,并使用
除了
。但问题是,如果在原始列表中都有一个元组
(“a”、“b”)
(“b”、“a”)
,那么在Python中如何做同样的事情呢?值得感谢的是,这可能导致返回的元组不在原始序列中;如果输入是
{b”,“a”}
,那么它将返回
{a”,“b”}
,而不是输出中的
{b”,“a”}
。@Servy是的,但我就是这样理解这个问题的。如果需要保留原始元素,我将返回dotnetfiddle.net并制作第二个版本。他希望具有相反顺序的值的对被视为相等,但这并不一定意味着可以返回不在原始集中的项。它可能很好,但可能不是,它没有定义。我喜欢这种方法,因为它很简单。但是实现IEqualityComparer感觉更“干净”的解决方案。+1我已经创建了测试程序,您的算法要快得多。在我的例子中,清除100000个随机生成的元组列表的结果是38251412ms,在您的例子中,对于相同的复制列表,清除结果是595329ms。删除了我的答案。
using System;
using System.Collections.Generic;

using System.Linq;

public class Program
{
    static List<Tuple<string, string>> myList = new List<Tuple<string, string>>()
    {
        Tuple.Create<string, string>("A", "B"),
        Tuple.Create<string, string>("B", "A"), // duplicate
        Tuple.Create<string, string>("C", "B"),
        Tuple.Create<string, string>("C", "B"), // duplicate
        Tuple.Create<string, string>("A", "D")              
    };

    public static void Main()
    {
        myList
            .Select(x => new[] { x.Item1, x.Item2 }.OrderBy(s => s).ToArray())
            .Select(x => Tuple.Create<string,string>(x[0], x[1]))
            .Distinct()
            .Dump();
    }
}
Dumping object(System.Linq.<DistinctIterator>d__81`1[Tuple`2[String,String]])
[
   {
   Item1  : A
   Item2  : B
   ToString(): (A, B)
   },
   {
   Item1  : B
   Item2  : C
   ToString(): (B, C)
   },
   {
   Item1  : A
   Item2  : D
   ToString(): (A, D)
   }
]
using System;
using System.Collections.Generic;

using System.Linq;

public class Program
{
    static List<Tuple<string, string>> myList = new List<Tuple<string, string>>()
    {
        Tuple.Create<string, string>("B", "A"),
        Tuple.Create<string, string>("A", "B"), // duplicate
        Tuple.Create<string, string>("C", "B"),
        Tuple.Create<string, string>("C", "B"), // duplicate
        Tuple.Create<string, string>("A", "D"),
        Tuple.Create<string, string>("E", "F"),
        Tuple.Create<string, string>("F", "E"), // duplicate        
    };

    public static void Main()
    {

        var result =
            from y in 
                from x in myList
                select new { Original = x, SortedPair = new[] { x.Item1, x.Item2 }.OrderBy(s => s).ToArray() }  
                group y by new { NormalizedTuple = Tuple.Create<string,string>(y.SortedPair[0], y.SortedPair[1]) } into grp
            select new { Pair = grp.Key.NormalizedTuple, Original = grp.First().Original };


        foreach(var item in result)
        {
            Console.WriteLine("Pair: {0} {1}", item.Original.Item1, item.Original.Item2);
        }
    }
}
Pair: B A
Pair: C B
Pair: A D
Pair: E F