ATeDe Ответов: 2

Поиск индексов элементов одного массива в другом с помощью LINQ


Даны два массива A и B, найти индекс от стихии Б

Dim A As String() = {"a", "b", "c", "d", "e", "f", "g", "h", "i"}
Dim B As String() = {"b", "d", "e"}

For Each item As String In B
    Dim index1 As Integer = Array.IndexOf(A, item)
    Console.WriteLine("{0} {1}", index1, item)
Next


1 б
3 d
4 е

Что я уже пробовал:

Мой код в "традиционном" варианте VB.NET работает, но я хочу преобразовать его с помощью LINQ.
Заранее спасибо.
Атеде

2 Ответов

Рейтинг:
14

Graeme_Grant

Вот один из способов...

Dim A As String() = {"a", "b", "c", "d", "e", "f", "g", "h", "i"}
Dim B As String() = {"b", "d", "e"}

Dim c = A.Select(Function(x, i) New KeyValuePair(Of String, Integer)(x, i)) _
         .Where(Function(x) B.Contains(x.Key))

For Each item In c
    Console.WriteLine("{0} - {1}", item.Key, item.Value)
Next


Maciej Los

5ed!

Graeme_Grant

Спасибо

ATeDe

Спасибо Грэм, хороший пример приложения LINQ. На самом деле вы дали мне указание, что KeyValuePair можно использовать для преобразования массива A в listA следующим образом:

Дим листа в виде списка(из KeyValuePair(строка, целое число)) = A. выберите(функция(х, я) новый KeyValuePair(строка, целое число)(X, я)).Список()

Graeme_Grant

Да... вы также можете использовать кортежи...

ATeDe

Да, и вместо того, чтобы использовать Dim A в качестве String (), listA может быть создана непосредственно, и тогда мы получим очень аккуратный оператор:

Дим с = листа.Где(функция(x) B. содержит(x.Key))
Для каждого элемента в C
Приставка.WriteLine("{0} {1}", предмет.Ключ, пункт.значение)
Следующий

Graeme_Grant

Да как ты мог. Я просто хотел, чтобы все было просто для тебя. Вы могли бы поставить все это так:

For Each item In (New String({"a", "b", "c", "d", "e", "f", "g", "h", "i"}) _
    .Select(Function(x, i) New KeyValuePair(Of String, Integer)(x, i)) _
    .Where(Function(x) (New String({"b", "d", "e"}).Contains(x.Key))))
    Console.WriteLine("{0} - {1}", item.Key, item.Value)
Next

Но тогда он жестко закодирован и не так легко читается...

Рейтинг:
11

Maciej Los

В качестве альтернативы решению № 1 из Graeme_Grant[^], "переведенная" (в запрос Linq) версия вашего решения-это:

Dim A As String() = {"a", "b", "c", "d", "e", "f", "g", "h", "i"}
Dim B As String() = {"b", "d", "e"}

Dim result = A.Where(Function(q) B.Any(Function(w) q=w)). _
	Select(Function(x) New With _
		{ _
			.Index = Array.IndexOf(A, x), _
			.Value = x _
		})


Я бы предложил проверить следующую документацию MSDN для получения более подробной информации:
Перечислимый.Метод Intersect(TSource) (IEnumerable(TSource), IEnumerable(TSource)) (System.Linq)[^]
Перечислимый.Кроме Метода(TSource) (IEnumerable(TSource), IEnumerable(TSource)) (System.Linq)[^]
Перечислимый.Метод ElementAt(TSource) (IEnumerable(TSource), Int32) (System.Linq)[^]


Graeme_Grant

5 объед прямой перевод :)

Maciej Los

Спасибо, Грэм

Richard Deeming

Хотя это не совсем прямой перевод. :)

Исходный код повторяется через B, находя индекс в A для каждого элемента. Ваша версия начинается с A, фильтрует его по элементам, которые существуют в B, а затем находит индекс в A.

Настоящий перевод был бы таков:

Dim result = B.Select(Function (x) New With
{
    .Value = x,
    .Index = Array.IndexOf(A, x)
})

Maciej Los

ОК. Это почти прямой перевод ;)
Ваше здоровье!
Мацей

ATeDe

Отличная штука, Ричард! Большое спасибо!