Подтвердить что ты не робот

Можно ли использовать LINQ для поиска пробелов в отсортированном списке?

Возможно ли использовать LINQ таким образом, чтобы я мог определить, что "9"  является первым отсутствующим значением в отсортированном списке без использования цикла for и сравнения каждого значения с соседним с ним?

var listStringVals = new [] { "7", "13", "8", "12", "10", "11", "14" };
// sort list to "7","8","10","11","12","13","14"
var sortedList = listStringVals.OrderBy(c => int.Parse(c)).ToList();
// need some magic here to get the first gap in the sorted list
4b9b3361

Ответ 1

Пусть

var strings = new string[] { "7", "13", "8", "12", "10", "11", "14" };

Тогда

var list = Array.ConvertAll(strings, s => Int32.Parse(s)).OrderBy(i => i);
// or
var list = strings.Select(s => int.Parse(s)).OrderBy(i => i);
// or
var list = strings.OrderBy(s => int.Parse(s));

(обратите внимание на этот вопрос)

а затем

var result = Enumerable.Range(list.Min(), list.Count).Except(list).First(); // 9
// or
int min = list.Min(), max = list.Max();
var result = Enumerable.Range(min, max - min + 1).Except(list).First();

Ответ 2

Здесь вы можете начать (я использовал здесь значения int):

List<int> listStringVals = (new int[] { 7, 13, 8, 12, 10, 11, 14 }).ToList();
List<int> SortedList = listStringVals.OrderBy(c => c).ToList();
List<int> Gaps = Enumerable.Range(SortedList.First(), 
                                  SortedList.Last() - SortedList.First() + 1)
                           .Except(SortedList).ToList();

Ответ 3

var listStringVals = new string[] {"7", "13", "8", "12", "10", "11", "14"};
var sortedInts = listStringVals.Select(c => int.Parse(c)).OrderBy(x => x);
var noGaps = Enumerable.Range(sortedInts.First(), 
                              sortedInts.Last() - sortedInts.First() + 1);
var missing = noGaps.Except(sortedInts).Select(x => x.ToString()).First();

Изменить: создание фиксированного диапазона благодаря Ответу BeemerGuy. Все еще оставляя мое, так как он не игнорирует уродство списка представлений string int:)

Ответ 4

(абатищев избил меня до удара, но его ответ в любом случае лучше. Однако, поскольку альтернативные решения одной и той же проблемы могут быть забавными, я все равно размещаю это.)

Взламывание взлома. Но работайте, если вы действительно хотите это сделать. Производительность будет ужасной, потому что эта техника не остановится, когда найдет ответ - она ​​всегда будет перебирать все числа! Но он будет работать:

public static int FindFirstMissing(IEnumerable<int> sequence)
{
    bool found = false;

    int agg = sequence.Aggregate((aggregate, next) => {
        if (found)
            return aggregate;

        if (next - aggregate != 1) {
            found = true;
            return aggregate + 1;
        }

        return next;
    });

    if (!found)
        throw new ArgumentException("sequence", "Contains no missing numbers.");

    return agg;
}

Ответ 5

string firstGap = sortedList
    .Zip(sortedList.Skip(1), (f, s) => Tuple.Create(f, s))
    .First(tup => (int.Parse(tup.Item1) + 1) != int.Parse(tup.Item2)).Item1;

Должен дать вам первый элемент перед первым зазором, поэтому первый отсутствующий элемент:

string gap = (int.Parse(firstGap) + 1).ToString();

Ответ 6

Немного поздно, но я думаю, что это классный способ сделать это:

List<int> listStringVals = (new int[] { 7, 13, 8, 12, 10, 11, 14 }).ToList();
            listStringVals.Sort();
            return listStringVals.Skip(1).Select((x, i) => x - listStringVals[i] == 1).Any(x => !x);

Ответ 7

Почему бы просто не использовать All, поскольку все члены коллекции должны соответствовать критериям...

Пример

someVar.All(v => someVar.Contains(v + 1) || v == someVar.Last())

Тогда вам не нужно заказывать и лучше.

Вы можете сортировать после этого шага или даже во время, если вам нужно, но я лично просто использую отсортированную коллекцию и сделаю это для меня.

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

например.

someVar.All((v) => { 
    bool result = someVar.Contains(v + 1) || v == someVar.Last();
    if(!result) someList.Add(v);
    return true;
});

Проверка счетчика списка (который может быть заказан) для ненулевого значения, чтобы указать, удовлетворен ли он или нет.