如何使用 LINQ、C# 检查整数序列是否交替出现偶数和奇数
How to check if the sequence of ints has even and odd numbers alternating using LINQ, C#
假设我在 c# 中有一个整数列表,如下所示:
List<int> numbers = new List<int>() { 1, 2, 7, 20, 3 };
有没有办法检查它有 alternating odd 和 even 数字它(如上例所示:如果 one 如果它们是 even 那么 next 必须是 奇数 反之亦然)?
我知道在循环中检查它很简单,但我正在尝试仅使用 LINQ 和扩展方法来实现它。
我们来分析一下问题。交替奇偶校验是什么意思?
index : value : value + index
------------------------------
0 : 1 : 1 - note, all sums are odd
1 : 2 : 3
2 : 7 : 9
....
或
index : value : value + index
------------------------------
0 : 2 : 2 - note, all sums are even
1 : 1 : 2
2 : 6 : 8
....
如您所见(并且您可以轻松证明)交替奇偶校验意味着
index + value
总和是 all odd
或 all even
。让我们在 Linq 的帮助下检查一下:
List<int> numbers = new List<int>() { 1, 2, 7, 20, 3, 79 };
bool result = numbers
.DefaultIfEmpty()
.Select((item, index) => Math.Abs((long)item + (long)index))
.Aggregate((s, a) => s % 2 == a % 2 ? s % 2 : -1) >= 0;
实施注意事项:
DefaultIfEmpty()
- 空序列具有交替的所有(全零)值;然而,Aggregate
没有任何聚合并抛出异常。让我们把空序列变成一个元素序列。
(long)
为了防止整数溢出(int.MaxValue + index
可以超出int
范围)
Math.Abs
:c#可以return负余数(例如-1 % 2
);我们不想对此进行额外检查,所以让我们使用绝对值
- 然而,我们可以在最后的
Aggregate
中利用这个效果 (-1 % 2 == -1
)
我希望更容易理解的扩展方法解决方案:
public static bool IsAlternating(this IEnumerable<int> source) {
if (null == source)
throw new ArgumentNullException(nameof(source));
bool expectedZero = false;
bool first = true;
foreach (int item in source) {
int actual = item % 2;
if (first) {
first = false;
expectedZero = actual == 0;
}
else if (actual == 0 && !expectedZero || actual != 0 && expectedZero)
return false;
expectedZero = !expectedZero;
}
return true;
}
请注意,循环解决方案(扩展方法)更有效:它returns false
立即 当模式不符合时。
你可以用这种方式使用 LINQ。您可以检查添加位置是否有最后一个偶数项或偶数位是否有奇数项。
List<int> numbers = new List<int>() { 1, 2, 7, 20, 3 };
var temp = numbers.Where((x, i) => (i % 2 == 0 && x % 2 == 0) || (i % 2 == 1 && x % 2 == 1)).Take(1);
int count = temp.Count();
if(count == 0)
{
//true
}
else
{
//false
}
注意:假设您希望偶数出现在偶数位,奇数出现在奇数位。
您可以使用 Aggregate
来确定序列是否交替。
假设如果有 0 个或 1 个元素,则结果为真。
您可以根据需要修改此逻辑。
基于此可以创建一个扩展方法:
public static bool IsAlternatingParitySequenceVerbose(this IEnumerable<int> col)
{
// state:
// -1 - sequence is not alternating
// 0 - even
// 1 - odd
if (!col.Any())
return true;
//check if first value is even
var firstState = Math.Abs(col.First() % 2);
var IsAlternating = col.Skip(1).Aggregate(firstState, (state, val) =>
{
if (state == -1)
return -1;
var current = Math.Abs(val % 2);
if (current == state)
return -1;
return current;
});
return IsAlternating != -1;
}
然后用它做一个单行:
public static bool IsAlternatingParitySequence(this IEnumerable<int> col) =>
!col.Any()
|| col.Skip(1).Aggregate(Math.Abs(col.First() % 2), (state, val) =>
state == -1
? -1
: Math.Abs(val % 2) is var current && current == state
? -1
: current
) != -1;
假设我在 c# 中有一个整数列表,如下所示:
List<int> numbers = new List<int>() { 1, 2, 7, 20, 3 };
有没有办法检查它有 alternating odd 和 even 数字它(如上例所示:如果 one 如果它们是 even 那么 next 必须是 奇数 反之亦然)?
我知道在循环中检查它很简单,但我正在尝试仅使用 LINQ 和扩展方法来实现它。
我们来分析一下问题。交替奇偶校验是什么意思?
index : value : value + index
------------------------------
0 : 1 : 1 - note, all sums are odd
1 : 2 : 3
2 : 7 : 9
....
或
index : value : value + index
------------------------------
0 : 2 : 2 - note, all sums are even
1 : 1 : 2
2 : 6 : 8
....
如您所见(并且您可以轻松证明)交替奇偶校验意味着
index + value
总和是 all odd
或 all even
。让我们在 Linq 的帮助下检查一下:
List<int> numbers = new List<int>() { 1, 2, 7, 20, 3, 79 };
bool result = numbers
.DefaultIfEmpty()
.Select((item, index) => Math.Abs((long)item + (long)index))
.Aggregate((s, a) => s % 2 == a % 2 ? s % 2 : -1) >= 0;
实施注意事项:
DefaultIfEmpty()
- 空序列具有交替的所有(全零)值;然而,Aggregate
没有任何聚合并抛出异常。让我们把空序列变成一个元素序列。(long)
为了防止整数溢出(int.MaxValue + index
可以超出int
范围)Math.Abs
:c#可以return负余数(例如-1 % 2
);我们不想对此进行额外检查,所以让我们使用绝对值- 然而,我们可以在最后的
Aggregate
中利用这个效果 (
-1 % 2 == -1
)
我希望更容易理解的扩展方法解决方案:
public static bool IsAlternating(this IEnumerable<int> source) {
if (null == source)
throw new ArgumentNullException(nameof(source));
bool expectedZero = false;
bool first = true;
foreach (int item in source) {
int actual = item % 2;
if (first) {
first = false;
expectedZero = actual == 0;
}
else if (actual == 0 && !expectedZero || actual != 0 && expectedZero)
return false;
expectedZero = !expectedZero;
}
return true;
}
请注意,循环解决方案(扩展方法)更有效:它returns false
立即 当模式不符合时。
你可以用这种方式使用 LINQ。您可以检查添加位置是否有最后一个偶数项或偶数位是否有奇数项。
List<int> numbers = new List<int>() { 1, 2, 7, 20, 3 };
var temp = numbers.Where((x, i) => (i % 2 == 0 && x % 2 == 0) || (i % 2 == 1 && x % 2 == 1)).Take(1);
int count = temp.Count();
if(count == 0)
{
//true
}
else
{
//false
}
注意:假设您希望偶数出现在偶数位,奇数出现在奇数位。
您可以使用 Aggregate
来确定序列是否交替。
假设如果有 0 个或 1 个元素,则结果为真。 您可以根据需要修改此逻辑。
基于此可以创建一个扩展方法:
public static bool IsAlternatingParitySequenceVerbose(this IEnumerable<int> col)
{
// state:
// -1 - sequence is not alternating
// 0 - even
// 1 - odd
if (!col.Any())
return true;
//check if first value is even
var firstState = Math.Abs(col.First() % 2);
var IsAlternating = col.Skip(1).Aggregate(firstState, (state, val) =>
{
if (state == -1)
return -1;
var current = Math.Abs(val % 2);
if (current == state)
return -1;
return current;
});
return IsAlternating != -1;
}
然后用它做一个单行:
public static bool IsAlternatingParitySequence(this IEnumerable<int> col) =>
!col.Any()
|| col.Skip(1).Aggregate(Math.Abs(col.First() % 2), (state, val) =>
state == -1
? -1
: Math.Abs(val % 2) is var current && current == state
? -1
: current
) != -1;