简体   繁体   English

C#使用Where(Linq)筛选具有四个条件的列表

[英]C# using Where (Linq) to filter a list with four condition

I have a list got it from the database (using dataset): 我有一个列表从数据库中获取(使用数据集):

IEnumerable<DataSet.spGetDataRow> MyList = new DataSetTableAdapters.spGetDataTableAdapter().GetData(Date1, Date2, PID, RID).ToList();    

and I have 4 checkbox 我有4个复选框

<asp:CheckBox ID="CheckBox1" Text="1" runat="server" />
<asp:CheckBox ID="CheckBox2" Text="2" runat="server" />
<asp:CheckBox ID="CheckBox3" Text="3" runat="server" />
<asp:CheckBox ID="CheckBox4" Text="4" runat="server" />

what I need is to filter 'MyList' 我需要过滤“ MyList”

I did the following: 我做了以下事情:

if (CheckBox1.Checked && !CheckBox2.Checked && !CheckBox3.Checked && !CheckBox4.Checked)
{
    MyList = MyList.Where(a => a.Avg < 2);
}
else if (CheckBox2.Checked && !CheckBox1.Checked && !CheckBox3.Checked && !CheckBox4.Checked)
{
    MyList = MyList.Where(a => a.Avg >= 2 && a.Avg < 3);
}
else if (CheckBox3.Checked && !CheckBox2.Checked && !CheckBox1.Checked && !CheckBox4.Checked)
{
    MyList = MyList.Where(a => a.Avg >= 3 && a.Avg < 6);
}
else if (CheckBox4.Checked && !CheckBox2.Checked && !CheckBox3.Checked && !CheckBox1.Checked)
{
    MyList = MyList.Where(a => a.Avg >= 6);
}

this work great if I need to check only one checkbox at a time, but what if I want to check 2 or 3 at a time. 如果我一次只需要选中一个复选框,那么这项工作非常有用,但是如果我一次只需要选中2或3,该怎么办。

creating so many if conditions is not the best solution, I need to do it through linq if posible 如果条件不是最好的解决方案,那么创建那么多,如果可能,我需要通过linq来完成

what I was doing is to create a new MyList, and 'concat' the filtered one into it, but it didn't end well. 我正在做的是创建一个新的MyList,并将过滤后的MyList“连接”到其中,但是效果并不理想。

Thank you in advance. 先感谢您。

Do it vice versa. 反之亦然。 Test each checkbox. 测试每个复选框。 If it is not checked remove the entries which are represented by this checkbox. 如果选中,请删除此复选框代表的条目。 Or better take those which are not represented. 或更好地采取那些没有代表。 So if CheckBox1 is not checked take those entries which are not <2 that means they are >=2. 因此,如果选中CheckBox1,则采用那些小于2的条目,这意味着它们大于等于2。

    if (!CheckBox1.Checked)
    {
        MyList = MyList.Where(a => a.Avg >= 2);
    }
    if (!CheckBox2.Checked)
    {
        MyList = MyList.Where(a => a.Avg < 2 || a.Avg >= 3);
    }
    if (!CheckBox3.Checked)
    {
        MyList = MyList.Where(a => a.Avg < 3 || a.Avg >= 6);
    }
    if (!CheckBox4.Checked)
    {
        MyList = MyList.Where(a => a.Avg < 6);
    }

In a next step you should precalculate the average values so this function isn't called so many times. 在下一步中,您应该预先计算平均值,这样就不会多次调用此函数。 Eg build tuples (row, average) then filter the average values and get back the rows by extracting them from the tuples. 例如,建立元组(行,平均值),然后过滤平均值,并通过从元组中提取行来取回行。

Your question intrigues me to find a solution using a Dictionary. 您的问题使我很想用词典找到解决方案。 This will leave your code to a simple two lines like these (well also a simple function is required) 这会将您的代码留给像这样的简单两行(同样需要一个简单的函数)

int index = CreateIndexFromCheckboxSelected();
var result = MyList.Where(x => dict[index].Invoke(x));

To reach this solution you need to build a Dictionary with a numeric key and a Func as value. 要实现此解决方案,您需要使用数字键和Func作为值来构建一个Dictionary。

The numeric key is a byte sum of the various checkbox respecting a boolean logic in which the checkBox1 represents the bit at position 1, checkbox2 the bit at position 2 and so on.... 数字键是关于布尔逻辑的各个复选框的字节总和,其中,checkBox1表示位置1的位,checkbox2表示位置2的位,依此类推。

The Func part is the lambda expression required by the where clause applied to your list of sqGetDataRow elements Func部分是应用于您的sqGetDataRow元素列表的where子句所需的lambda表达式

You need 16 entries in this dictionary, one for each of the possible combination of the 4 checkboxes, each entry contains the lambda expression to be used in the where clause to extract the required spGetDataRow element. 您需要在此字典中有16个条目,每个条目对应4个复选框的可能组合,每个条目都包含lambda表达式,该表达式将在where子句中使用以提取所需的spGetDataRow元素。

Dictionary<int, Func<spGetDataRow,bool>> dict = new Dictionary<int, Func<spGetDataRow, bool>>()
{
    {0, (spGetDataRow a) => true},                      // No checkboxes checked return all
    {1, (spGetDataRow a) => a.Avg < 2},                 // Only checkbox1 checked
    {2, (spGetDataRow a) => a.Avg >= 2 && a.Avg < 3},   // Only checkbox2 checked
    {3, (spGetDataRow a) => a.Avg ????},                // CheckBox1 AND Checkbox2 checked
    {4, (spGetDataRow a) => a.Avg >= 3 && a.Avg < 6},   // CheckBox3 checked
    {5, (spGetDataRow a) => a.Avg ????},                // CheckBox3 + ChecBox1 checked
    {6, (spGetDataRow a) =>  a.Avg >= 2 && a.Avg < 6},  // CheckBox3 + CheckBox2 checked
    {7, (spGetDataRow a) => a.Avg ????},                // CheckBox3 + CheckBox2 + CheckBox1 checked    
    {8, (spGetDataRow a) => a.Avg >= 6},                // CheckBox4 checked
    {9, (spGetDataRow a) => a.Avg ????},                // CheckBox4 + CheckBox1 checked
    {10, (spGetDataRow a) => a.Avg ????},               // CheckBox4 + CheckBox2 checked
    {11, (spGetDataRow a) => a.Avg ????},               // CheckBox4 + CheckBox2 + CheckBox1 checked    
    {12, (spGetDataRow a) => a.Avg ????},               // CheckBox4 + CheckBox3 checked
    {13, (spGetDataRow a) => a.Avg ????},               // CheckBox4 + CheckBox3 + CheckBox1 checked
    {14, (spGetDataRow a) => a.Avg ????},               // CheckBox4 + CheckBox3 + CheckBox2 checked
    {15, (spGetDataRow a) => true}                      // All checkboxes selected return all
};

The example above contains the correct lambda only for the info I can extract from your question, but as you can see it is just a matter to replace the placeholder lambda with the correct one that you require for the various combinations of checkboxes. 上面的示例仅包含我可以从您的问题中提取的信息的正确lambda,但是如您所见,将占位符lambda替换为各种复选框组合所需的正确lambda只是一个问题。

To complete the example there is just one piece missing, but this is pretty trivial 为了完成该示例,仅遗漏了一部分,但这是微不足道的

public int CreateIndexFromCheckboxSelected()
{
    int chk1 = (CheckBox1.Checked ? 1 : 0);
    int chk2 = (CheckBox2.Checked ? 2 : 0);
    int chk3 = (CheckBox3.Checked ? 4 : 0);
    int chk4 = (CheckBox4.Checked ? 8 : 0);
    return (chk1 + chk2 + chk3 + chk4);
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM