C# 如何获取二进制搜索的第一个索引&x27;结果如何?
我有一些问题。我有两个清单,例如:C# 如何获取二进制搜索的第一个索引&x27;结果如何?,c#,linq,list,C#,Linq,List,我有一些问题。我有两个清单,例如: List<int> firstList = new List<int> { 1, 2, 2, 3, 5}; List<int> secondList = new List<int> { 2, 3, 1 }; List firstList=新列表{1,2,2,3,5}; List secondList=新列表{2,3,1}; ⇒ 真正的结果是:{1,3,0} 我想得到firstList中存在的secondLi
List<int> firstList = new List<int> { 1, 2, 2, 3, 5};
List<int> secondList = new List<int> { 2, 3, 1 };
List firstList=新列表{1,2,2,3,5};
List secondList=新列表{2,3,1};
⇒ 真正的结果是:{1,3,0}
我想得到firstList中存在的secondList中的第一个数字索引。我使用了list.BinarySearch()
但是结果是{2,3,0}
list firstList=newlist{1,2,2,3,5};
List<int> firstList = new List<int> { 1, 2, 2, 3, 5};
List<int> secondList = new List<int> { 2, 3, 1 };
var output = secondList.Select(item => firstList.IndexOf(item)); // [1 , 3 , 0]
List secondList=新列表{2,3,1};
var output=secondList.Select(item=>firstList.IndexOf(item));//[1 , 3 , 0]
您可以用BinarySearch逻辑替换IndexOf
,但是BinarySearch返回第一个匹配的元素索引,因此您不会得到最低的数字,IndexOf会返回最低的匹配索引。List firstList=新列表{1,2,2,3,5};
List secondList=新列表{2,3,1};
var output=secondList.Select(item=>firstList.IndexOf(item));//[1 , 3 , 0]
您可以用BinarySearch逻辑替换
IndexOf
,但是BinarySearch返回第一个匹配的元素索引,因此您不会得到最低的数字,IndexOf会返回最低的匹配索引。迭代第二个数组并获取第一个数组中元素的索引:
foreach (int item in secondList)
{
Console.WriteLine(firstList.IndexOf(item));
}
迭代第二个数组并获取第一个数组中元素的索引:
foreach (int item in secondList)
{
Console.WriteLine(firstList.IndexOf(item));
}
问题在于,当列表包含与您的情况相同的重复值时,
BinarySearch
方法将返回任何匹配值的索引(非确定性)
要获得所需的结果,可以创建并使用如下自定义扩展方法:
public static class ListExtensions
{
public static int BinarySearchFirst<T>(this List<T> source, T item, IComparer<T> comparer = null)
{
if (comparer == null) comparer = Comparer<T>.Default;
int index = source.BinarySearch(item, comparer);
while (index > 0 && comparer.Compare(source[index], source[index - 1]) == 0)
index--;
return index;
}
}
问题在于,当列表包含与您的情况相同的重复值时,
BinarySearch
方法将返回任何匹配值的索引(非确定性)
要获得所需的结果,可以创建并使用如下自定义扩展方法:
public static class ListExtensions
{
public static int BinarySearchFirst<T>(this List<T> source, T item, IComparer<T> comparer = null)
{
if (comparer == null) comparer = Comparer<T>.Default;
int index = source.BinarySearch(item, comparer);
while (index > 0 && comparer.Compare(source[index], source[index - 1]) == 0)
index--;
return index;
}
}
如果您有一个较大的
firstList
,因此必须使用BinarySearch
尝试修改它:通过BinarySearch
查找项目(不保证是最左边的项目),然后在读取相同项目的同时向左移动:
List<int> firstList = new List<int> { 1, 2, 2, 3, 5 };
List<int> secondList = new List<int> { 2, 3, 1, 123 };
var result = secondList
.Select(item => firstList.BinarySearch(item))
.Select(index => index < 0 ? -1 : Enumerable
.Range(0, index + 1) // we have to scan [0..index] at the worst case
.Select(i => index - i) // scan in reverse
.TakeWhile(i => firstList[index] == firstList[i]) // take while items are the same
.Last()); // finally, we want the last item
如果您有一个较大的
firstList
,因此必须使用BinarySearch
尝试修改它:通过BinarySearch
查找项目(不保证是最左边的项目),然后在读取相同项目的同时向左移动:
List<int> firstList = new List<int> { 1, 2, 2, 3, 5 };
List<int> secondList = new List<int> { 2, 3, 1, 123 };
var result = secondList
.Select(item => firstList.BinarySearch(item))
.Select(index => index < 0 ? -1 : Enumerable
.Range(0, index + 1) // we have to scan [0..index] at the worst case
.Select(i => index - i) // scan in reverse
.TakeWhile(i => firstList[index] == firstList[i]) // take while items are the same
.Last()); // finally, we want the last item
C++对此有一个标准库函数,称为 这是一个C#实现。如果要搜索大型集合,此选项非常有用:
public static int LowerBound<T>(IList<T> values, T target, int first, int last)
where T : IComparable<T>
{
int left = first;
int right = last;
while (left < right)
{
int mid = left + (right - left) / 2;
var middle = values[mid];
if (middle.CompareTo(target) < 0)
left = mid + 1;
else
right = mid;
}
return left;
}
public static int LowerBound(IList值、T目标、int first、int last)
其中T:i可比较
{
int左=第一;
int right=last;
while(左<右)
{
int mid=左+(右-左)/2;
var middle=数值[mid];
if(中间比较(目标)<0)
左=中+1;
其他的
右=中;
}
左转;
}
对于找不到的元素,它不会返回-1,因此要解决这个问题,我们可以这样包装它:
public static int LowerBoundOrMinusOne<T>(IList<T> values, T target, int first, int last)
where T : IComparable<T>
{
int result = LowerBound(values, target, first, last);
if (result >= last || result < first || values[result].CompareTo(target) != 0)
return -1;
return result;
}
public static int LowerBoundOrMinusOne(IList值、T目标、int first、int last)
其中T:i可比较
{
int result=LowerBound(值、目标、第一个、最后一个);
如果(结果>=最后一个| |结果<第一个| |值[结果]。比较(目标)!=0)
返回-1;
返回结果;
}
以下是您如何使用它:
List<int> firstList = new List<int> { 1, 2, 2, 3, 5 };
List<int> secondList = new List<int> { 2, 3, 1 };
List<int> result = secondList
.Select(value => LowerBoundOrMinusOne(firstList, value, 0, firstList.Count))
.ToList();
Console.WriteLine(string.Join(", ", result));
List firstList=新列表{1,2,2,3,5};
List secondList=新列表{2,3,1};
列表结果=第二个列表
.Select(value=>lowerbounderminusone(firstList,value,0,firstList.Count))
.ToList();
Console.WriteLine(string.Join(“,”,result));
当然,这主要有利于大型列表,因为它的复杂性是O(Log2(N))而不是O(N)。C++有一个标准的库函数来实现这一点 这是一个C#实现。如果要搜索大型集合,此选项非常有用:
public static int LowerBound<T>(IList<T> values, T target, int first, int last)
where T : IComparable<T>
{
int left = first;
int right = last;
while (left < right)
{
int mid = left + (right - left) / 2;
var middle = values[mid];
if (middle.CompareTo(target) < 0)
left = mid + 1;
else
right = mid;
}
return left;
}
public static int LowerBound(IList值、T目标、int first、int last)
其中T:i可比较
{
int左=第一;
int right=last;
while(左<右)
{
int mid=左+(右-左)/2;
var middle=数值[mid];
if(中间比较(目标)<0)
左=中+1;
其他的
右=中;
}
左转;
}
对于找不到的元素,它不会返回-1,因此要解决这个问题,我们可以这样包装它:
public static int LowerBoundOrMinusOne<T>(IList<T> values, T target, int first, int last)
where T : IComparable<T>
{
int result = LowerBound(values, target, first, last);
if (result >= last || result < first || values[result].CompareTo(target) != 0)
return -1;
return result;
}
public static int LowerBoundOrMinusOne(IList值、T目标、int first、int last)
其中T:i可比较
{
int result=LowerBound(值、目标、第一个、最后一个);
如果(结果>=最后一个| |结果<第一个| |值[结果]。比较(目标)!=0)
返回-1;
返回结果;
}
以下是您如何使用它:
List<int> firstList = new List<int> { 1, 2, 2, 3, 5 };
List<int> secondList = new List<int> { 2, 3, 1 };
List<int> result = secondList
.Select(value => LowerBoundOrMinusOne(firstList, value, 0, firstList.Count))
.ToList();
Console.WriteLine(string.Join(", ", result));
List firstList=新列表{1,2,2,3,5};
List secondList=新列表{2,3,1};
列表结果=第二个列表
.Select(value=>lowerbounderminusone(firstList,value,0,firstList.Count))
.ToList();
Console.WriteLine(string.Join(“,”,result));
当然,这主要对大型列表有利,因为它的复杂性是O(Log2(N))而不是O(N)。BinarySearch不保证第一个匹配,它用于搜索和插入排序的集合。是的,我得到了它。谢谢BinarySearch不保证第一个匹配,它用于搜索和插入已排序的集合。是的,我找到了。谢谢,如果第二个列表中的数字在第一个列表中不存在,我必须返回-1。我应该使用SingleorDefault?IndexOf将返回-1,继续并尝试现在如果第二个列表中的数字在第一个列表中不存在,我必须返回-1。我应该使用SingleorDefault?IndexOf将返回-1,如果没有元素,请继续尝试他想要的
-1
found@Ofiris:谢谢你,我明白了;只需对三值运算符进行一点修改,他需要-1