LINQ - 匹配值,如果没有,return NULL 元素
LINQ - Match value, if not, return NULL element
我有一个给定的日期,我想获取 table 上大于给定日期的元素,但如果找不到,我想 return 具有NULL
日期。
例如:
Table:
如果给定的日期是,例如,2019-10-20,我想 return ID 为 3 的元素。
如果给定的日期是,例如,2019-11-20,我想 return ID 为 4 的元素。
我试过这样做:
var parameter = _db.Parameter
.OrderBy(x => x.EndDate)
.First(givenDate < x.EndDate) || x.EndDate == null);
但它总是 return 最后一个元素。我需要做什么?
你可以试试这个:
var query = _db.Parameter
.OrderBy(x => x.EndDate)
.ToList();
var parameter = query.FirstOrDefault(x => givenDate < x.EndDate);
if ( parameter == null )
parameter = query.FirstOrDefault(x => x.EndDate == null);
if ( parameter == null )
...
else
...
我们在日期上创建一个初始排序查询,用一个列表来评估查询。
接下来我们检查第一个 givenDate 是否匹配所需的结果。
否则我们尝试获取第一个空行。
那你就可以办理最后的案子了。
为避免对查询进行两次解析,您可以使用:
TheTypeOfParameter parameterFound = null;
TheTypeOfParameter parameterHavingDateNotNull = null;
TheTypeOfParameter parameterHavingDateNull = null;
bool foundDateNull = false;
bool foundDateNotNull = false;
foreach ( var item in query )
{
if ( !foundDateNull && item.EndDate == null )
{
parameterHavingDateNull = item;
foundDateNull = true;
}
else
if ( !foundDateNotNull && item.EndDate > givenDate )
foundDateNotNull = true;
if ( !foundDateNotNull )
parameterHavingDateNotNull = item;
if ( foundDateNotNull || foundDateNull )
break;
}
parameterFound = parameterHavingDateNotNull != null
? parameterHavingDateNotNull
: parameterHavingDateNull;
因为我不能测试和调试,所以我希望这个循环能工作...
如评论中所述,NULL将在排序后排在第一位。
如果您尝试以下操作会怎样:
var parameter = _db.Parameter
.Where(x => (x.EndDate > givenDate) || (x.EndDate == null))
.OrderBy(x => x.EndDate)
.Last();
仅选择较早的日期后,选择最新的日期。如果列表中只有一个元素(NULL 元素),则选择该元素。
我会通过不使用 LINQ 来优化代码:
var parameter = _db.Parameter[0]; // you may need to handle that there's at least 1 item.
for (int i = 1; i < _db.Parameter.Count; i++)
{
var param = _db.Parameter[i];
if (param.EndDate > givenDate)
{ // param is good
if (parameter.EndDate == null || parameter.EndDate > param.EndDate)
parameter = param; // replace parameter with param
}
else if (parameter.EndDate != null && parameter.EndDate < givenDate)
{ // parameter precedes given date, replace it!
parameter = param;
}
}
与目前提供的其他解决方案不同,这将只遍历您的列表一次。
如果您必须使用 LINQ 并希望迭代一次,也许您可以使用下面的方法,但它 return 是动态的,因此您需要将其转换回一个Parameter
。它的工作原理是将 NULL
替换为 DateTime.MaxValue
,这样当您执行 OrderBy
时,NULL
的条目将排在底部。
var param = _db.Parameter
.Select(x => new
{
ID = x.ID,
EndDate = (x.EndDate.HasValue) ? x.EndDate : DateTime.MaxValue,
Value = x.Value
})
.OrderBy(x => x.EndDate)
.FirstOrDefault();
var parameter = new Parameter()
{
ID = param.ID,
EndDate = (param.EndDate == DateTime.MaxValue) ? null : param.EndDate,
Value = param.Value
};
我有一个给定的日期,我想获取 table 上大于给定日期的元素,但如果找不到,我想 return 具有NULL
日期。
例如:
Table:
如果给定的日期是,例如,2019-10-20,我想 return ID 为 3 的元素。
如果给定的日期是,例如,2019-11-20,我想 return ID 为 4 的元素。
我试过这样做:
var parameter = _db.Parameter
.OrderBy(x => x.EndDate)
.First(givenDate < x.EndDate) || x.EndDate == null);
但它总是 return 最后一个元素。我需要做什么?
你可以试试这个:
var query = _db.Parameter
.OrderBy(x => x.EndDate)
.ToList();
var parameter = query.FirstOrDefault(x => givenDate < x.EndDate);
if ( parameter == null )
parameter = query.FirstOrDefault(x => x.EndDate == null);
if ( parameter == null )
...
else
...
我们在日期上创建一个初始排序查询,用一个列表来评估查询。
接下来我们检查第一个 givenDate 是否匹配所需的结果。
否则我们尝试获取第一个空行。
那你就可以办理最后的案子了。
为避免对查询进行两次解析,您可以使用:
TheTypeOfParameter parameterFound = null;
TheTypeOfParameter parameterHavingDateNotNull = null;
TheTypeOfParameter parameterHavingDateNull = null;
bool foundDateNull = false;
bool foundDateNotNull = false;
foreach ( var item in query )
{
if ( !foundDateNull && item.EndDate == null )
{
parameterHavingDateNull = item;
foundDateNull = true;
}
else
if ( !foundDateNotNull && item.EndDate > givenDate )
foundDateNotNull = true;
if ( !foundDateNotNull )
parameterHavingDateNotNull = item;
if ( foundDateNotNull || foundDateNull )
break;
}
parameterFound = parameterHavingDateNotNull != null
? parameterHavingDateNotNull
: parameterHavingDateNull;
因为我不能测试和调试,所以我希望这个循环能工作...
如评论中所述,NULL将在排序后排在第一位。 如果您尝试以下操作会怎样:
var parameter = _db.Parameter
.Where(x => (x.EndDate > givenDate) || (x.EndDate == null))
.OrderBy(x => x.EndDate)
.Last();
仅选择较早的日期后,选择最新的日期。如果列表中只有一个元素(NULL 元素),则选择该元素。
我会通过不使用 LINQ 来优化代码:
var parameter = _db.Parameter[0]; // you may need to handle that there's at least 1 item.
for (int i = 1; i < _db.Parameter.Count; i++)
{
var param = _db.Parameter[i];
if (param.EndDate > givenDate)
{ // param is good
if (parameter.EndDate == null || parameter.EndDate > param.EndDate)
parameter = param; // replace parameter with param
}
else if (parameter.EndDate != null && parameter.EndDate < givenDate)
{ // parameter precedes given date, replace it!
parameter = param;
}
}
与目前提供的其他解决方案不同,这将只遍历您的列表一次。
如果您必须使用 LINQ 并希望迭代一次,也许您可以使用下面的方法,但它 return 是动态的,因此您需要将其转换回一个Parameter
。它的工作原理是将 NULL
替换为 DateTime.MaxValue
,这样当您执行 OrderBy
时,NULL
的条目将排在底部。
var param = _db.Parameter
.Select(x => new
{
ID = x.ID,
EndDate = (x.EndDate.HasValue) ? x.EndDate : DateTime.MaxValue,
Value = x.Value
})
.OrderBy(x => x.EndDate)
.FirstOrDefault();
var parameter = new Parameter()
{
ID = param.ID,
EndDate = (param.EndDate == DateTime.MaxValue) ? null : param.EndDate,
Value = param.Value
};