返回类型以显示重复项

时间:2019-03-14 09:23:34

标签: c# string linq

我是一种在DataTable中查找重复项的方法。现在,我必须返回重复值(如果存在于主代码块中)并以comma separated的形式显示。

我应该如何编辑我的方法以返回重复的值并以comma separated的形式显示?

// what should be the return type of this method ???
public Find_Duplicate_Symbol_Number(DataTable dt)
{
    try
    {
        var dup_result = from c in dt.AsEnumerable()
                     group c by new
                     {
                         RowId = c.Field<string>("SYMBOL_NO")
                     } into g
                     where g.Count() > 1
                     select new
                     {
                         g.Key.RowId
                     };

        // how to return dup_result ???             
    }
    catch (Exception)
    {

        throw;
    }
} 

/// ** main code block ** ///
Find_Duplicate_Symbol_Number(DataTable dt)

如果存在重复项,如何从主代码块调用此函数并以逗号分隔的形式显示重复值?

2 个答案:

答案 0 :(得分:2)

您可以使用string.Join将所有数字连接在一起:

public string FindDuplicateSymbolNumber(DataTable dt) 
{
    return string.Join(", ", from c in dt.AsEnumerable()
                             group 1 by c.Field<string>("SYMBOL_NO") into g
                             where g.Skip(1).Any()
                             select g.Key.RowId);
}

还可以查看查询中的更改-无需投影包含单个字段的匿名类型,只需投影字段。另外,除了计数(并消耗整个集合)之外,只需跳过每个组中的第一个项目,然后检查之后是否还有其他项目-意味着该组中不止一个项目。


如果您只想返回重复ID的列表,则:

public IEnumerable<string> FindDuplicateSymbolNumber(DataTable dt) 
{
    return from c in dt.AsEnumerable()
           group 1 by c.Field<string>("SYMBOL_NO") into g
           where g.Skip(1).Any()
           select g.Key.RowId;
}

答案 1 :(得分:0)

So apparently you have a DataTable with a column SYMBOL_NO. This column contains a string value. You want to count all duplicate string values in this column and display it in format:

2 duplicate SYMBOL NUMBERS found 00157 & 00158

Where instead of 2 you want the actual number of found duplicates, and instead of 00157 and 00158 you want the actual duplicate symbols

It will be easier for you to understand your problem and to test the solution if you don't put all code in one function. Separate your code into smaller functions:

  • (A) Given an input DataTable, return from every row the string value at column SYMBOL_NO.
  • (B) Given an input enumerable sequence of strings, return every string from the input string that occurs more than once
  • (C) given a sequence of strings, write a text similar to:

.

2 duplicate SYMBOL NUMBERS found 00157 & 00158

Where instead of 2, the actual number of elements in the strings, and 00157 & 00158 the elements from the string. Keep in mind that there may be no duplicates. In that case:

0 duplicate SYMBOL NUMBERS found

How about this:

DataTable dt = ...

// (A) extract the SYMBOL_NO
var string = dt.AsEnumerable().Select(row => row.Field<string>("SYMBOL_NO");

// (B) Find duplicates
// group the input texts into groups of same string 
// and remember if there are duplicates

.GroupBy(text => text, // ResultSelector: take the text (in Key) and all items with this Key (key, textsEqualToThisKey) => new { SymbolNo = text, IsDuplicate = textsEqualToThisKey.Skip(1).Any(), // more efficient than Count() })

// (C) Keep only those SymbolNos that have duplicates
.Where(group => group.IsDuplicate)
.Select(group => group.SymbolNo

// (D) From the remaining duplicates make a string
// TODO

The last one is the most difficult, because the text before the first item is different than the text before every other items. Furthermore, the text is different if there are no items found at all.

My advice would be to create an extension function, this would be the easiest way to understand what happens

static string ToDuplicateDescription(this IEnumerable<string> duplicates)
{

    var enumerator = duplicates.GetEnumerator();

    if (enumerator.MoveNext())
    {
        // there is at least one duplicate. The first one is without ampersand
        int count = 1;
        StringBuilder sb = new StringBuilder();
        // add the count later
        sb.AppendFormat(" duplicate SYMBOL NUMBERS found {0}", enumerator.Current);

        // are there more duplicates?
        while (enumerator.MoveNext())
        {
            ++count;
            sb.AppendFormat(" & {0}", enumerator.Current);
        }
        // if here, no more duplicates.
        return count.ToString() + sb.ToString();
    }
    else
    {
        // no duplicates at all
        return "0 duplicate SYMBOL NUMBERS found";
    }
}

Usage: (continuing the LINQ above)

 // (D) From the remaining duplicates make a string
 .ToDuplicateDescription();