Its hard to say without you posting the type of original collection, but the problem seems to be exactly what is stated in your error message.
LINQ works in iterative steps and after call to Select(dr => dr.Field<string>("MergedName").Replace("'", "''"))
you next expresion works with collection of strings. And there in no method .Field
on String type
I guess you could try simplifying C.Field<string>("MergedName").ToLower()
in your where clause to C.ToLower()
You are also not doing any grouping in your second statement so Select(g => g.Key)
wont work, because there is no Key property on String type either.
This addresses only syntax, your Where clause still looks pretty weird. You are comparing each string to itself.
You could try something like
var names = result.AsEnumerable()
.Select(dr => dr.Field<string("MergedName").Replace("'", "''").ToLower().Trim())
.ToList(); //ToList not necessary here, but could prevent multiple executions of the expresion
var duplicates = names.Where(n => names.Any(m => n.IndexOf(m) != -1)) //quadratic complexity
.ToList();
Just put your own condition into Any part of the last statement, you have two strings m
and n
there and can compare them however you wish.
This is definitely not the best performing solution of your problem, but it uses LINQ as in your questinon and is easy to write and understand.
After clarification:
var enumerableResult = result.AsEnumerable();
var duplicates = enumerableResult.
.Where(dr => enumerableResult.Any(dr2 => /*your comparison*/)
.ToList();
comparison could be something like:
dr.Field<string>("MergedName").Replace("'", "''").Trim().ToLower().IndexOf(dr2.Field<string>("MergedName").Replace("'", "''").Trim().ToLower()) != -1
This condition is based on the one in your question, not the one in your comment. But you dont need to use this inline sytax and can call some custom method, so it would look like .Any(dr2 => AreSamePerson(dr, dr2))
This has again quadratic complexity, it is problem only if you have a lot of records to compare.
Now you get collection of your person objects instead of just strings. Keep in mind that you cant just delete members of duplicate collection from original one but some rather complex logic is needed.
So the best solution seems to be:
var duplicates = result.AsEnumerable()
.GroupBy(x => x, new PersonyComparer() )
.Where(g => g.Count() > 1)
class PersonyComparer : IEqualityComparer<Person>//person is the type of objects that are in starting collection
{
public bool Equals(Person b1, Person b2)
{
if (b2 == null && b1 == null)
return true;
else if (b1 == null | b2 == null)
return false;
if(/*your condition*/)
return true;
else
return false;
}
public int GetHashCode(Person bx)
{
return 0; //you must make sure that objects that are equal have same hashcode
}
}
This can lead to problems, so make sure that your equal function is symetric (if a==b then b == a) and transitive (if a==b and b==c then a==c). Otherwise your groupping could be screwed a bit.
Then you can iterate over the objects of duplicate collection
foreach(var pgroup in duplicates)
{
foreach(var person in pgroup .Skip(1))
{
//remove from original collection
}
}