在浮点列表中查找NaN,并将上一个和下一个元素设置为NaN

时间:2015-07-09 12:49:50

标签: c# linq list nan

我有一个List<float>,其中有NaNNaN。我想按1展开NaN地区。换句话说,如果我找到NaN元素,我希望上一个和下一个元素也变为List<float> l = new List<float>() { float.NaN, 1, 2, 3, float.NaN, float.NaN, float.NaN, 4, 5, 6, float.NaN, 7, 8, float.NaN, 9 }; Console.WriteLine(string.Join(" ", l)); List<float> ll = l.Select(item => item).ToList(); // clone list for (int i = 0; i < l.Count; i++) { if (!float.IsNaN(l[i])) continue; if (i > 0) ll[i - 1] = float.NaN; ll[i] = float.NaN; if (i < l.Count - 1) ll[i + 1] = float.NaN; } Console.WriteLine(string.Join(" ", ll)); Console.ReadKey();

我制作了一些有效的代码,但在我看来它可能更简单。有什么建议吗?

NaN   1   2   3 NaN NaN NaN   4   5   6 NaN   7   8 NaN   9
NaN NaN   2 NaN NaN NaN NaN NaN   5 NaN NaN NaN NaN NaN NaN 

输出:

deckOf4List.next()

4 个答案:

答案 0 :(得分:4)

以下是仅使用一个选择的实现:

l.Select((item, index) => index > 0 && float.IsNaN(l[index - 1]) || index < l.Count - 1 && float.IsNaN(l[index + 1]) ? float.NaN : item)

答案 1 :(得分:2)

您可以使用其他方法展开NaN 。请注意扩展消费的第一个和最后一个数字系列:

  

x --- NaN

     

x y --- NaN NaN

     

x y z --- NaN y NaN

     

x y z w --- NaN y z NaN

     

...

不理想,只是一个例子(这里是fiddle):

var list = new List<float>() { float.NaN, 1, 2, 3, float.NaN, float.NaN, float.NaN, 4, 5, 6, float.NaN, 7, 8, float.NaN, 9, float.NaN, 10, 11, 12, 13 };
Console.WriteLine(string.Join(" ", list.Select(o => o.ToString().PadLeft(3))));
int counter = 0;
for (int i = 0; i < list.Count; i++)
{
    if(!float.IsNaN(list[i]))
    {
        // increment counter if number and replace first in serie with NaN
        if(counter++ == 0)
            list[i] = float.NaN;
    }
    else
        // serie finished? replace last number in it with NaN
        if(counter != 0)
        {
            list[i - 1] = float.NaN;
            counter = 0; // reset count
        }
}
// special test if last item in list is a number
// serie finished? replace last number in it with NaN
if(counter != 0)
    list[list.Count - 1] = float.NaN;
Console.WriteLine(string.Join(" ", list.Select(o => o.ToString().PadLeft(3))));

输出(我最后添加了4个数字的系列):

NaN   1   2   3 NaN NaN NaN   4   5   6 NaN   7   8 NaN   9 NaN  10  11  12  13
NaN NaN   2 NaN NaN NaN NaN NaN   5 NaN NaN NaN NaN NaN NaN NaN NaN  11  12 NaN

答案 2 :(得分:2)

您可以使用Linq获取需要更改的索引,然后强制更新列表的副本。

   var theNewNanIndexes = Enumerable.Range( 0, l.Count )
        .Where( num => float.IsNaN(l[num]))
        .SelectMany( num => new[]{ num - 1, num + 1  } )
        .Where( num => num >= 0 && num < l.Count) ;


ll = new List<float>(l);
theNewNanIndexes.ToList().ForEach( num => ll[num] = float.NaN );

答案 3 :(得分:1)

这个怎么样:

private bool IsAdjacentNaN(List<float> list, int index)
{
    var beforeNaN = index != 0 && float.IsNaN(list[index - 1]);
    var afterNaN = (index + 1 != list.Count) && float.IsNaN(list[index + 1]);
    return beforeNaN || afterNaN;
}

List<float> l = ...;
var results = l.Select((x,i) => IsAdjacentNaN(l,i) ? float.NaN : x);

在这个例子中,IsAdjacentNaN抽象了复杂性,因此你的lambda可以更简单。