从C#列表对象中计算具有相同模式的元素

从C#列表对象中计算具有相同模式的元素,c#,list,linq,count,C#,List,Linq,Count,嗨,我有一个C#list对象,它包含我的sql表中的员工数据。现在有一个列名称BadgeNumber,它有6个字符或13个字符的字符串值。我需要所有6个字符和13个字符徽章的计数 我使用foreach循环来获取计数,它工作正常。但我想知道是否有更快的解决办法 下面是我当前的实现 var empDetails = GetAllEmployeeDetails(); int internalEmpCount; int contractEmpCount; foreach (var emp in em

嗨,我有一个C#list对象,它包含我的sql表中的员工数据。现在有一个列名称BadgeNumber,它有6个字符或13个字符的字符串值。我需要所有6个字符和13个字符徽章的计数

我使用foreach循环来获取计数,它工作正常。但我想知道是否有更快的解决办法

下面是我当前的实现

var empDetails = GetAllEmployeeDetails();

int internalEmpCount;
int contractEmpCount;

foreach (var emp in empDetails)
{
    if (emp.BadgeNumber.Length == 6)
        internalEmpCount++;
    else if (emp.BadgeNumber.Length == 13)
        contractEmpCount++;
}
Console.WriteLine("{0}, {1}", internalEmpCount, contractEmpCount);

我看过这个解决方案,但更多的是关于重复值,因此我不认为我可以在这里使用group by,因为在我的例子中,所有徽章编号都是唯一的,唯一的相似性是徽章编号的长度。但任何建议或意见都将不胜感激

不,这没关系。但是,您不需要进行13长度限制检查。仅当您具有输入验证时才可以执行此操作。您可以将其更改为else,稍微加快执行速度。

不,这没关系。但是,您不需要进行13长度限制检查。仅当您具有输入验证时才可以执行此操作。您可以将其更改为else,以略微加快执行速度。

您也可以按徽章编号长度分组。如果你把结果输入字典,你可以很容易地得到你需要的值

var empDetails = GetAllEmployeeDetails();
var result = empDetails.GroupBy(x => x.BadgeNumber.Length)
                       .ToDictionary(k => k.Key, v => v.Count());
Console.WriteLine("{0}, {1}", result[6], result[13]);

请注意,这并不比您的解决方案更快、更高效、更易读

您还可以按徽章编号长度分组。如果你把结果输入字典,你可以很容易地得到你需要的值

var empDetails = GetAllEmployeeDetails();
var result = empDetails.GroupBy(x => x.BadgeNumber.Length)
                       .ToDictionary(k => k.Key, v => v.Count());
Console.WriteLine("{0}, {1}", result[6], result[13]);

请注意,这并不比您的解决方案更快、更高效、更易读

您的代码只枚举一次序列。要计算请求的值,需要枚举完整的序列。因此,您和LINQ都无法提高效率

您所能获得的唯一效率是用一个switch语句替换两个if语句。这样,属性长度将只计算一次:

switch (emp.BadgeNumber.Length)
{
    case 6:
        internalEmpCount++;
        break;
    case 13:)
        contractEmpCount++;
        break;
    // default: do nothing
}
或者,如果您完全确定长度为6或13:

if (emp.BadgeNumber.Length == 6)
    internalEmpCount++;
else
    contractEmpCount++;
更高效:让您的数据库进行计数 数据库查询中较慢的部分之一是将所选数据从DBMS传输到本地进程。因此,限制传输的数据量是明智的

<强>如果列表的唯一原因是对元素进行计数,请考虑让数据库只对最终结果进行计数和传输,而不是完整列表。

IQueryable<EmpDetail> empDetails = ...

var result = empDetails
    // keep only the empDetail that you want to count:
    .Where(empDetail => empDetail.BadgeNumber.Length == 6
                     || empDetail.BadgeNumber.Length == 13)

    // make groups with same BadgeNumber.Length:
    .GroupBy(empDetail => empDetail.BadgeNumber.Length,

         // ResultSelector:
         (length, empDetailsWithThisLength) => new
         {
             Length = length,
             Count = empDetailsWithThisLength.Count,
         });
IQueryable empDetails=。。。
var result=empDetails
//仅保留要计算的详细信息:
.其中(empDetail=>empDetail.BadgeNumber.Length==6
||empDetail.BadgeNumber.Length==13)
//使用相同的徽章编号创建组。长度:
.GroupBy(empDetail=>empDetail.BadgeNumber.Length,
//结果选择器:
(长度,empDetailsWithThisLength)=>新建
{
长度=长度,
Count=empDetails此长度。Count,
});

结果:两个项目的集合,每个项目带有[长度,计数]。因此,只传输4个整数。

您的代码只枚举一次序列。要计算请求的值,需要枚举完整的序列。因此,您和LINQ都无法提高效率

您所能获得的唯一效率是用一个switch语句替换两个if语句。这样,属性长度将只计算一次:

switch (emp.BadgeNumber.Length)
{
    case 6:
        internalEmpCount++;
        break;
    case 13:)
        contractEmpCount++;
        break;
    // default: do nothing
}
或者,如果您完全确定长度为6或13:

if (emp.BadgeNumber.Length == 6)
    internalEmpCount++;
else
    contractEmpCount++;
更高效:让您的数据库进行计数 数据库查询中较慢的部分之一是将所选数据从DBMS传输到本地进程。因此,限制传输的数据量是明智的

<强>如果列表的唯一原因是对元素进行计数,请考虑让数据库只对最终结果进行计数和传输,而不是完整列表。

IQueryable<EmpDetail> empDetails = ...

var result = empDetails
    // keep only the empDetail that you want to count:
    .Where(empDetail => empDetail.BadgeNumber.Length == 6
                     || empDetail.BadgeNumber.Length == 13)

    // make groups with same BadgeNumber.Length:
    .GroupBy(empDetail => empDetail.BadgeNumber.Length,

         // ResultSelector:
         (length, empDetailsWithThisLength) => new
         {
             Length = length,
             Count = empDetailsWithThisLength.Count,
         });
IQueryable empDetails=。。。
var result=empDetails
//仅保留要计算的详细信息:
.其中(empDetail=>empDetail.BadgeNumber.Length==6
||empDetail.BadgeNumber.Length==13)
//使用相同的徽章编号创建组。长度:
.GroupBy(empDetail=>empDetail.BadgeNumber.Length,
//结果选择器:
(长度,empDetailsWithThisLength)=>新建
{
长度=长度,
Count=empDetails此长度。Count,
});

结果:两个项目的集合,每个项目带有[长度,计数]。因此,只传输4个整数。

我认为这种方法没有任何问题。O(n)获取计数。如果BadgeNumber只有6个字符或13个字符的值,则不需要第二个If语句。那么您只需要计算一个&从全部细节中计算另一个。@Naphstor这是最快的解决方案。有更明确、更可读的版本,但最终都会变慢这是最快的。。您必须迭代所有项目(除非之前已按长度排序)。。正如所指出的,如果让DB为你做这件事,你可以做得更快。类似于SELECT LENGTH(Emp.BadgeNumber),COUNT(1)FROM Emp GROUP BY LENGTH(Emp.BadgeNumber),我认为这种方法没有任何问题。O(n)获取计数。如果BadgeNumber只有6个字符或13个字符的值,则不需要第二个If语句。那么您只需要计算一个&从全部细节中计算另一个。@Naphstor这是最快的解决方案。有更明确、更可读的版本,但最终都会变慢这是最快的。。您必须迭代所有项目(除非之前已按长度排序)。。正如所指出的,如果让DB为你做这件事,你可以做得更快。类似于选择长度(Emp.BadgeNumber),按长度从Emp组中计数(1)(Emp.BadgeNumber)是的,你是对的,但我可能有一个条件