【问题标题】:How to assign two lists in a linq query with some conditions?如何在某些条件下在 linq 查询中分配两个列表?
【发布时间】:2014-07-08 09:40:09
【问题描述】:

我有两个列表,我以这种方式分配其中一个:

var query = Enumerable.Range(0, 1440).Select((n, index) =>
{
    if ((index >= 525 && index <= 544) || (index >= 600 && index <= 749) || (index >= 810 && index <= 1079) || (index >= 1300 && index <= 1439))
        return 0;
    else if (index >= 1080 && index <= 1299)
        return 1;
    else if (index >= 545 && index <= 599)
        return 3;
    else if (index >= 750 && index <= 809)
        return 4;
    else
        return 2;
}).ToList();

我的第二个列表名为 lst2。我想根据我的第一个列表查询为其分配“0”或“1”。因此,如果查询为“1”或“2”,则 lst2 的相同索引和先前为“0”值的索引应为“1”。如果查询列表是“3”或“4”,lst2 的相同索引和之前的索引为“1”值,应该是“0”。此外,如果查询的第一个索引具有“3”或“4”值,则 lst2 的相同索引应为“0”。例如;

query = {3,3,3,0,0,0,2,2,0,0,0,0,4,4,4,4,0,0,0,0,1,1,1,0,0,2,2,0,0,4,4}
lst2  = {0,0,0,1,1,1,1,1,0,0,0,0,0,0,0,0,1,1,1,1,1,1,1,1,1,1,1,0,0,0,0}

我该怎么做?

编辑: 如果查询的任何索引具有 3 或 4 值,则 lst2 的相同索引必须具有 0 值。如果查询的任何索引具有 3 或 4 值且前一个索引具有 0 值,则 lst2 的相同索引必须具有 0 值。同样地;如果查询的任何索引具有 1 或 2 值,则 lst2 的相同索引必须具有 1 值。如果查询的任何索引具有 1 或 2 值且前一个索引具有 0 值,则 lst2 的相同索引必须具有 1 值。

【问题讨论】:

  • 该列表有 1440 个元素,在您的示例数据(querylst2)中,您只显示了一个摘录,对吗?一般来说,如果索引(+ 以前的索引)如此重要,LINQ 不是最佳选择。使用for-loop。
  • 是的。借调。使用 for 循环并同时写入两个列表。在延迟执行或任何其他方面,您并没有从 linq 中获得太多好处,因此无需太依赖它。
  • 没错。 lst2 应该具有相同的大小,这是一个摘录。我怎样才能完成?
  • 我认为你应该更详细地解释你想要什么。我仍然不明白你什么时候想在 lst2 中有一个 0 或 1。也许用例会有所帮助。你可能会做一些不必要的复杂的事情;)

标签: c# linq list indices


【解决方案1】:

我希望这是你需要的:

    int n = 1440;
    byte[] query = new byte[n];
    byte[] lst2 = new byte[n];
    byte mode = 0;
    bool first = true;
    for(int index = n-1; index >= 0; index--)
    {

        if ((index >= 525 && index <= 544) || (index >= 600 && index <= 749) || (index >= 810 && index <= 1079) || (index >= 1300 && index <= 1439))
            query[index] = 0;
        else if (index >= 1080 && index <= 1299)
            query[index] = 1;
        else if (index >= 545 && index <= 599)
            query[index] = 3;
        else if (index >= 750 && index <= 809)
            query[index] = 4;
        else
            query[index] = 2;

        if(query[index] == 3 || query[index] == 4)
        {
            mode = 0;
            lst2[index] = 0;
        }
        else if(query[index] == 1 || query[index] == 2)
        {
            if(first)
            {
                //change ending zeros to 1
                for(int j=index+1; j < n; j++)
                    lst2[j] = 1;

                first = false;
            }
            mode = 1;
            lst2[index] = 1;
        }
        else
        {   
            lst2[index] = mode;
        }
    }

【讨论】:

  • 感谢您的回答。这有些错误。例如;如果查询 = {2,2,2,0,0,0,3,3,0,0,0,0,4,4,4,4,0,0,0,0,1,1,1, 0,0,0,0} 那么 lst2 应该是 {1,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,1 ,1,1,1,1,1,1,1,1}。但是这个解决方案的结果是 {1,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,1,1,1,1, 1,0,0,0,0}。可以做什么?
  • 我不知道结尾零的规则。只是继续以前的模式?
  • 你是对的。实际上;如果查询的第一个值不是 0,那么 lst2 的相同索引应该是 0。如果查询的最后一个值是 0,那么 lst2 的相同索引应该是 1。对不起,我想我没有说什么。
【解决方案2】:

另一种方法,仅在需要时填充跟踪 0。性能方面,最好还是反向循环,但我只是看到 T_D 已经这样做了,所以就前瞻 -> 回溯而言,以下基本相同,但使用其他语法和不同的尾随 0 填充符。

    var arr = new int[query.Count];
    int cnt = query.Count - 1, toappendindex = -1;
    Func<int,int,int> getval = (ind, val) =>
    {
        if (val == 3 || val == 4) return  0;
        if (val == 2 || val == 1) return  1;
        if (ind == cnt) return -1;
        return arr[ind + 1];
    };   
    for (int ind = cnt; ind >= 0; ind-- ) 
    {
        if ((arr[ind] = getval(ind,query[ind])) == -1)
            toappendindex = ind; //only if there are trailing 0's
    }
    if (toappendindex > 0) 
        for (; toappendindex < arr.Length; toappendindex++) arr[toappendindex] = arr[toappendindex - 1];

    //var lst2 = arr.ToList(); if list is needed instead of array, otherwise arr could be used directly

【讨论】:

    【解决方案3】:

    尝试这样做。

            List<int> query = Enumerable.Range(0, 1440).Select((n, index) =>
            {
                if ((index >= 525 && index <= 544) || (index >= 600 && index <= 749) || (index >= 810 && index <= 1079) || (index >= 1300 && index <= 1439))
                    return 0;
                else if (index >= 1080 && index <= 1299)
                    return 1;
                else if (index >= 545 && index <= 599)
                    return 3;
                else if (index >= 750 && index <= 809)
                    return 4;
                else
                    return 2;
            }).ToList();
    
            Console.WriteLine(string.Concat("{", string.Join(",", query.ToArray()), "}"));
    
            List<int> lst2 = Enumerable.Range(0, 1440).Select((n, index) =>
            {
                if (query[index] == 1 || query[index] == 2)
                    return 1;
                else if (query[index] == 3 || query[index] == 4)
                    return 0;
                else
                {
                    int retval = 1;
                    //look ahead
                    for (int i = index; i < query.Count; i++)
                    {
                        if (query[i] == 1 || query[i] == 2)
                        {
                            break;
                        }
                        if (query[i] == 3 || query[i] == 4)
                        {
                            retval = 0;
                            break;
                        }
                    }
                    return retval;
                }
            }).ToList();
    
            Console.WriteLine(string.Concat("{", string.Join(",", lst2.ToArray()), "}"));
    

    如果这是您要找的,请告诉我。如果您愿意,可以将 List 替换为 var。我只是喜欢它的强类型,以便我可以轻松地检查输出。

    【讨论】:

    • 谢谢,但这不是我想要的。我已经用更多细节修改了这个问题。
    • 我已经修改了代码以说明最后一个 0。
    • 输出 {2,2,2,0,0,0,3,3,0,0,0,0,4,4,4,4,0,0,0, 0,1,1,1,0,0,0,0} 现在是 {1,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0 ,1,1,1,1,1,1,1,1,1,1,1}
    猜你喜欢
    • 2017-07-15
    • 2017-10-08
    • 2011-04-11
    • 1970-01-01
    • 2018-11-14
    • 1970-01-01
    • 1970-01-01
    • 2018-09-06
    • 2020-03-04
    相关资源
    最近更新 更多