I'm having a List of String like
List<string> MyList = new List<string>
{
"A-B",
"B-A",
"C-D",
"C-E",
"D-C",
"D-E",
"E-C",
"E-D",
"F-G",
"G-F"
};
I need to remove duplicate from the List i.e, if "A-B" and "B-A" exist then开发者_如何学JAVA i need to keep only "A-B" (First entry)
So the result will be like
"A-B"
"C-D"
"C-E"
"D-E"
"F-G"
Is there any way to do this using LINQ?
Implement IEqualityComparer witch returns true on Equals("A-B", "B-A"). And use Enumerable.Distinct method
This returns the sequence you look for:
var result = MyList
.Select(s => s.Split('-').OrderBy(s1 => s1))
.Select(a => string.Join("-", a.ToArray()))
.Distinct();
foreach (var str in result)
{
Console.WriteLine(str);
}
In short: split each string on the -
character into two-element arrays. Sort each array, and join them back together. Then you can simply use Distinct
to get the unique values.
Update: when thinking a bit more, I realized that you can easily remove one of the Select
calls:
var result = MyList
.Select(s => string.Join("-", s.Split('-').OrderBy(s1 => s1).ToArray()))
.Distinct();
Disclaimer: this solution will always keep the value "A-B" over "B-A", regardless of the order in which the appear in the original sequence.
You can use the Enumerable.Distinct(IEnumerable<TSource>, IEqualityComparer<TSource>)
overload.
Now you just need to implement IEqualityComparer
. Here's something for you to get started:
class Comparer : IEqualityComparer<String>
{
public bool Equals(String s1, String s2)
{
// will need to test for nullity
return Reverse(s1).Equals(s2);
}
public int GetHashCode(String s)
{
// will have to implement this
}
}
For a Reverse()
implementation, see this question
You need to implement the IEqualityComparer like this:
public class CharComparer : IEqualityComparer<string>
{
#region IEqualityComparer<string> Members
public bool Equals(string x, string y)
{
if (x == y)
return true;
if (x.Length == 3 && y.Length == 3)
{
if (x[2] == y[0] && x[0] == y[2])
return true;
if (x[0] == y[2] && x[2] == y[0])
return true;
}
return false;
}
public int GetHashCode(string obj)
{
// return 0 to force the Equals to fire (otherwise it won't...!)
return 0;
}
#endregion
}
The sample program:
class Program
{
static void Main(string[] args)
{
List<string> MyList = new List<string>
{
"A-B",
"B-A",
"C-D",
"C-E",
"D-C",
"D-E",
"E-C",
"E-D",
"F-G",
"G-F"
};
var distinct = MyList.Distinct(new CharComparer());
foreach (string s in distinct)
Console.WriteLine(s);
Console.ReadLine();
}
}
The result:
"A-B" "C-D" "C-E" "D-E" "F-G"
Very basic, but could be written better (but it's just working):
class Comparer : IEqualityComparer<string>
{
public bool Equals(string x, string y)
{
return (x[0] == y[0] && x[2] == y[2]) || (x[0] == y[2] && x[2] == y[0]);
}
public int GetHashCode(string obj)
{
return 0;
}
}
var MyList = new List<String>
{
"A-B",
"B-A",
"C-D",
"C-E",
"D-C",
"D-E",
"E-C",
"E-D",
"F-G",
"G-F"
}
.Distinct(new Comparer());
foreach (var s in MyList)
{
Console.WriteLine(s);
}
int checkID = 0;
while (checkID < MyList.Count)
{
string szCheckItem = MyList[checkID];
string []Pairs = szCheckItem.Split("-".ToCharArray());
string szInvertItem = Pairs[1] + "-" + Pairs[0];
int i=checkID+1;
while (i < MyList.Count)
{
if((MyList[i] == szCheckItem) || (MyList[i] == szInvertItem))
{
MyList.RemoveAt(i);
continue;
}
i++;
}
checkID++;
}
精彩评论