NSIndexSet "-indexAtIndex:"? - PullRequest
       29

NSIndexSet "-indexAtIndex:"?

14 голосов
/ 28 декабря 2010

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

Скажем, я хочу представить разреженный набор индексов с помощью NSIndexSet (что, конечно, для чего оно). Я могу использовать -firstIndex, чтобы получить самый низкий, и -lastIndex, чтобы получить самый высокий, но каков канонический способ получить один произвольный индекс в середине, учитывая его «индекс»? Документы оставили меня неясным.

например. если у меня установлен индекс с индексами {0, 5, 8, 10, 12, 28}, и я хочу сказать «дай мне четвертый индекс», и я ожидаю получить обратно 10 (или 12, я полагаю, в зависимости о том, считаю ли я ноль, но давайте не будем вдаваться в это, вы понимаете, о чем я).

Обратите внимание, что я не делаю "перечисление" по всему набору индексов. В данный момент времени я просто хочу узнать, какой n-й индекс в наборе имеет числовой порядок.

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

Я что-то упускаю из виду?

Спасибо!

Ответы [ 4 ]

7 голосов
/ 28 декабря 2010

NSIndexSet не предназначен для такого доступа.Обычно вы перечисляете индексы в наборе, например так:

NSUInteger idx = [theSet indexGreaterThanOrEqualToIndex: 0];
while (idx != NSNotFound) {
    // idx equals the next index in the set.
    idx = [theSet indexGreaterThanIndex: idx];
}

@ Ричард указывает, что этот цикл for проще:

for (NSUInteger i = [indexSet firstIndex]; i != NSNotFound; i = [indexSet indexGreaterThanIndex:i]) {
    // i equals the next index in the set.
}

Есть некоторые блочные методы, которыеявляются новыми для NSIndexSet в Mac OS X 10.6 / iOS 4.0, но я еще не рассмотрел их.

Это должно быть тривиально изменить в приведенном выше примере, чтобы сохранить количество индексов иостановитесь, когда он достигнет четвертого индекса в наборе.;)

4 голосов
/ 28 декабря 2010

Полагаю, NSIndexSet хранит свои индексы с использованием диапазонов, поэтому не всегда есть быстрый способ вернуть индекс nth. Вы можете перечислить счетчик до тех пор, пока он не достигнет целевого индекса:

NSUInteger index = [indexSet firstIndex];

for (NSUInteger i = 0, target = 4; i < target; i++)
  index = [indexSet indexGreaterThanIndex:index];

Это должно дать вам 4-й индекс. Вы даже можете добавить метод как метод категории, если хотите:

- (NSUInteger)indexAtIndex:(NSUInteger)anIndex
{
    if (anIndex >= [self count])
      return NSNotFound;

    NSUInteger index = [indexSet firstIndex];
    for (NSUInteger i = 0; i < anIndex; i++)
      index = [self indexGreaterThanIndex:index];
    return index;
}

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

3 голосов
/ 28 декабря 2010

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

[мой акцент]

На самом деле, нет, это не так.Документация гласит:

Не следует использовать наборы индексов для хранения произвольной коллекции целочисленных значений, поскольку индексы хранят индексы в виде отсортированных диапазонов.

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

0 голосов
/ 08 сентября 2017

Еще одно решение:

- (NSUInteger)indexAtIndex:(NSUInteger)index {
   __block NSUInteger result = NSNotFound;
   __block NSUInteger aCounter = 0;

   [self enumerateIndexesUsingBlock:^(NSUInteger idx, BOOL * _Nonnull stop) {
      if (aCounter == index) {
         result = idx;
         *stop = YES;

      } else {
         aCounter++;
      }
   }];

   return result;
}
...