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

C# 在浮动列表中查找NaN,并将上一个和下一个元素设置为NaN,c#,linq,list,nan,C#,Linq,List,Nan,我有一个列表,其中有一些NaN。我想通过1扩展NaN区域。换句话说,如果我找到一个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.

我有一个
列表
,其中有一些
NaN
。我想通过
1
扩展
NaN
区域。换句话说,如果我找到一个
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();

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

l.Select((item, index) => index > 0 && float.IsNaN(l[index - 1]) || index < l.Count - 1 && float.IsNaN(l[index + 1]) ? float.NaN : item)
l.Select((项,索引)=>index>0&&float.IsNaN(l[index-1])| index
以下是一个只使用一个选择的实现:

l.Select((item, index) => index > 0 && float.IsNaN(l[index - 1]) || index < l.Count - 1 && float.IsNaN(l[index + 1]) ? float.NaN : item)
l.Select((项,索引)=>index>0&&float.IsNaN(l[index-1])| index
您可以使用另一种方法展开
NaN
。请注意,扩展使用的是一系列数字中的第一个和最后一个数字:

x---NaN

x y---楠楠楠

x y z---NaN y NaN

x y z w---NaN y z NaN

不理想,但有一个例子(这里是一个例子):


您可以使用另一种方法展开
NaN
。请注意,扩展使用的是一系列数字中的第一个和最后一个数字:

x---NaN

x y---楠楠楠

x y z---NaN y NaN

x y z w---NaN y z NaN

不理想,但有一个例子(这里是一个例子):


您可以使用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 );
var thenewnanindex=Enumerable.Range(0,l.Count)
.Where(num=>float.IsNaN(l[num]))
.SelectMany(num=>new[]{num-1,num+1})
其中(num=>num>=0&&numll[num]=float.NaN);

您可以使用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 );
var thenewnanindex=Enumerable.Range(0,l.Count)
.Where(num=>float.IsNaN(l[num]))
.SelectMany(num=>new[]{num-1,num+1})
其中(num=>num>=0&&numll[num]=float.NaN);
这个怎么样:

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);
private bool IsAdjacentNaN(列表,int索引)
{
var beforeNaN=index!=0&&float.IsNaN(列表[index-1]);
var afterNaN=(index+1!=list.Count)和&float.IsNaN(list[index+1]);
返回前| |后;;
}
列表l=。。。;
var结果=l.Select((x,i)=>IsAjacentNan(l,i)?float.NaN:x);
在本例中,IsAdjacentNaN抽象了复杂性,因此您的lambda可以更简单。

这个如何:

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);
private bool IsAdjacentNaN(列表,int索引)
{
var beforeNaN=index!=0&&float.IsNaN(列表[index-1]);
var afterNaN=(index+1!=list.Count)和&float.IsNaN(list[index+1]);
返回前| |后;;
}
列表l=。。。;
var结果=l.Select((x,i)=>IsAjacentNan(l,i)?float.NaN:x);


在本例中,IsAjacentNan抽象了复杂性,因此您的lambda可以更简单。

您不需要
ll[i]=float.NaNl.Select(item=>item).ToList()
可以是
l.ToList()
新列表(l)
。这些改进稍微简化了代码。您需要复制列表吗?我意识到当前的实现要求它避免将数组填充到底,但是如果您可以避免这种情况,您就不能修改集合吗?我可能首先为NaN创建一个索引列表,然后根据该列表找到应该更改的位置。此列表可能比复制的列表短。您不需要
ll[i]=float.NaNl.Select(item=>item).ToList()
可以是
l.ToList()
新列表(l)
。这些改进稍微简化了代码。您需要复制列表吗?我意识到当前的实现要求它避免将数组填充到底,但是如果您可以避免这种情况,您就不能修改集合吗?我可能首先为NaN创建一个索引列表,然后根据该列表找到应该更改的位置。这个列表可能会比复制的列表短。我喜欢这个列表,因为它可读性和简洁性。列表副本甚至不是必需的。如果SelectMany部分更改为:.SelectMany(num=>Enumerable.Range(num-margin,(margin*2)+1),则可以使用一个变量maring。为了可读性和简洁性,我喜欢这个。列表副本甚至不是必需的。如果SelectMany部分更改为:.SelectMany(num=>Enumerable.Range(num-margin,(margin*2)+1),则可以使用变量maring。如果列表中的最后一项是数字,则此项不起作用-它不会将
1 2 3
转换为
NaN 2 NaN
,而是
NaN 2 3
。然而人们盲目地支持这个错误的答案。@Sinatr不幸的是,你在问题中没有提到这个要求。要用NaN替换列表中的第一项和最后一项,您可以使用我的查询的修改版本:
l.Select((项,索引)=>index==0 | | index==l.Count-1 | | float.IsNaN(l[index-1])| float.IsNaN(l[index+1])?float.NaN:item)
我不是op。op隐式地提到了这一点(检查他的输入字符串和想要的结果)。上一条评论中的代码也不起作用。请随意使用它。您可以编辑您的答案,以添加改进的代码,如果您设法使其工作的话。@Sinatr,我很抱歉,但他甚至没有含蓄地提到这个要求。输入字符串中的最后一项是9(在原始问题中,而不是在您的答案中)。应该用NaN替换它,因为输入列表中的前一项是NaN,而不是因为它是列表中的最后一项。你的小提琴有毛病。你的密码