我有一個列表如下:查找數組中最接近的值與linq列表?
public static List<int[]> list = new List<int[]>();
另外我也有一個變量命名爲X,X可以採取任何價值。我想在list[?][1]
中找到與X最接近和最小的值。例如:
如果X是1300,我想要列表索引:1.或者如果X是700,我想採取索引:0.我怎樣才能通過linq做到這一點?或者,還有其他解決方案嗎?
在此先感謝。
我有一個列表如下:查找數組中最接近的值與linq列表?
public static List<int[]> list = new List<int[]>();
另外我也有一個變量命名爲X,X可以採取任何價值。我想在list[?][1]
中找到與X最接近和最小的值。例如:
如果X是1300,我想要列表索引:1.或者如果X是700,我想採取索引:0.我怎樣才能通過linq做到這一點?或者,還有其他解決方案嗎?
在此先感謝。
你可以做一個下面的方式(段假定,該列表不爲空)
var x = 700;
var result = list.Select((subList, idx) => new { Value = subList[1], Idx = idx })
.Where(elem => elem.Value < x)
.Select(elem => new { Diff = Math.Abs(x - elem.Value), elem.Idx })
.OrderBy(elem => elem.Diff).FirstOrDefault();
if (result != null)
{
return result.Idx;
}
// case - there is no such index
你就可以開始通過扁平化的元素以新的匿名類型,其中index
是外數組索引,和產品的內陣列中的值:
假設輸入和期望的目標值:
var target = 20;
var input = (new int[][]{new int[]{1,2,3}, new int[]{4,7,8}, new int[]{5,4}});
然後平坦化將是
var tmp = input.SelectMany((x, y) => x.Select(item =>
new {index = y, item = item, delta = Math.Abs(target - item)}));
現在,你可以找到最優三角洲:
var bestDelta = tmp.Min(x => x.delta);
而從這個很簡單,找到最佳匹配:
var result = tmp.FirstOrDefault(x => x.delta == bestDelta);
或者如果你喜歡簡單地獲得指數:
var index = tmp.Where(x => x.delta == bestDelta).Select(x => x.index).First();
這可以被重寫爲oneliner:
var result = input.SelectMany((x, y) =>
x.Select(item => new {index = y, item = item, delta = Math.Abs(target - item)}))
.OrderBy(x => x.delta).Select(x => x.index).First();
但我傾向於發現其他解決方案更具可讀性。
我知道你問了Linq解決方案,但我認爲非Linq解決方案也不錯。
如果你對非Linq解決方案感興趣,下面是一個(它確實使用Linq在一個地方,但真的這是拉伸點!)。
的興趣,FindClosestSmaller()
主要方法時,返回一個Tuple
其中.Item1
是包含小於或等於目標值最接近的值的外列表的索引,和.Item2
是匹配的索引內部陣列。
如果未找到小於或等於目標值的值,則.Item1
和.Item2
都將爲零。
請注意,FindClosestSmaller()
需要IEnumerable<IEnumerable<int>>
類型的參數,這意味着您可以將其用於大多數集合類型,並且不僅限於List<int[]>
。
using System;
using System.Collections.Generic;
using System.Linq;
namespace Demo
{
public static class Program
{
private static void Main()
{
var ints1 = new [] { 1, 480, 749, 270 };
var ints2 = new [] { 1, 810, 1080, 271 };
var ints3 = new [] { 1, 7680, 7949, 271 };
var intLists = new List<int[]> {ints1, ints2, ints3};
test(intLists, 1300);
test(intLists, 700);
test(intLists, 480);
test(intLists, 0);
}
private static void test(List<int[]> values, int target)
{
var result = FindClosestSmaller(values, target);
Console.WriteLine("Target {0} found: Outer index = {1}, Inner index = {2}", target, result.Item1, result.Item2);
}
public static Tuple<int, int> FindClosestSmaller(IEnumerable<IEnumerable<int>> sequences, int target)
{
int closest = int.MaxValue;
int closestInner = 0; // Setting these to zero means we take the first element of the
int closestOuter = 0; // first list if no smaller element is found.
int outer = 0;
foreach (var sequence in sequences)
{
int inner = 0;
foreach (int distance in sequence.Select(value => target - value))
{
if ((distance >= 0) && (distance < closest))
{
closest = distance;
closestInner = inner;
closestOuter = outer;
}
++inner;
}
++outer;
}
return new Tuple<int, int>(closestOuter, closestInner);
}
}
}
用於清潔代碼。 Linq解決方案非常難以維護,難以理解,這不是linq的地方。 – 2014-11-05 14:21:54
它是什麼你想要返回?索引?價值? – flindeberg 2014-11-05 09:06:02
(1)是否必須使用Linq? (2)正如弗林德伯格所問,你想要返回什麼?內部列表?內部列表+該列表中找到的元素的索引?外部列表索引+該列表中找到的元素的內部列表索引?或者是其他東西? – 2014-11-05 09:22:20
我想取最接近X值的變量索引。正如我的問題,如果X = 700,結果應該是0.因爲480是最接近和較小的值,並且它的列表索引是0. – 1teamsah 2014-11-05 10:49:42