2013-06-07 5 views
0

Я хочу знать, что является самым быстрым способом найти индекс элемента в списке. Причина, по которой я хочу знать, заключается в том, что я делаю рендеринг XNA, но я начал получать исключения из памяти на более крупных моделях, когда я использовал только буфер вершин, поэтому теперь я применил систему индексных буферов. Моя проблема в том, что теперь мне приходится постоянно сканировать список, содержащий все мои Vector3s, для индекса того, который я хочу разместить дальше в моем индексном буфере. Я в настоящее время сканирования для индексов, как это:C# Самый быстрый способ найти индекс элемента в списке

 for (int i = 1; i < circleVect.Length; i++) 
     { 
      indices.Add(vertices.FindIndex(v3 => v3 == circleVect[i])); 
      indices.Add(vertices.FindIndex(v3 => v3 == circleVect[i - 1])); 
      indices.Add(vertices.FindIndex(v3 => v3 == middle)); 
     } 

Это прекрасно работает для того, что это довольно медленно, за исключением. Для расчета одного цилиндра требуется почти 1 секунда, и у меня их более 70 000 в моей большой модели. Поэтому я смотрю экран загрузки более 20 минут при загрузке моей более крупной модели и все еще не завершен. Это, к сожалению, просто неприемлемо. Если я попробую загрузить мою меньшую модель, это займет более 5 минут, тогда как неиндексированный загрузчик займет всего секунду или около того.

У меня нет абсолютно никакого формального обучения на C# и даже меньше в XNA, поэтому я знаю, что это, вероятно, очень неэффективный способ расчета индексов, поэтому я бы поэтому его оценил, если бы кто-нибудь из вас мог помочь мне в создании более эффективного импортера ,

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

+0

Если вершины отсортированы, самым быстрым способом будет использование двоичного поиска. Изменение между списком и массивом ничего не изменит (если вы не используете связанный список). Вы должны опубликовать то, что вы пытаетесь выполнить, а не «как я могу сделать это быстрее», так как я не думаю, что вы можете получить гораздо быстрее, чем то, что у вас есть сейчас, но то, что у вас сейчас, не идеально, и вы, вероятно, должны быть глядя на другие структуры данных. –

+0

Что именно вы хотите знать? Я в основном читаю из формата, который содержит много строк, которые представляют цилиндры. Затем я вычисляю квадрат (на данный момент) на концах бота и четыре квадроцикла для их соединения. Вершины для двух квадратов и их центров добавляются в список, а остальные затем вычисляются, как показано выше, путем определения вектора 3, поиска его индекса и добавления его в список. – Gerharddc

+0

Вы просто пытались использовать IndexOf вместо FindIndex? Определенно накладные расходы связаны с прохождением лямбды для каждой находки. Не сказать, что это ответ, но я думаю, что это может многое помочь. –

ответ

0

В вашем коде вы прокручиваете свои вершины по 3 раза по одной для каждой строки FindIndex. Вместо этого используйте один для цикла и траверсы и проверьте все три условия за 1 проход.

+0

Это действительно звучит неплохо, но не могли бы вы дать мне объяснение, как это сделать или, возможно, сделать пример? – Gerharddc

0
for (int i = 1; i < circleVect.Length; i++) 
{ 
    for (int j = 0; j < vertices.Count; j++) 
    { 
     var v3 = vertices[j]; 
     if (v3 == circleVect[i] || v3 == circleVect[i - 1] || v3 == middle) 
      indices.Add(j); 
    } 
} 

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

+0

вершины - это список, а не массив, поэтому я думаю, что вам нужно просто изменить вершины. Длина до вершин. Значение – Gerharddc

0

Ваш главный убийца выполнения выполняет поиск в списке из 70 000 предметов, которые занимают 70 000 операций. Это будет работать намного быстрее, чем поиск в списке.

Dictionary<int, Vertice> vertices = new Dictionary<int, Vertice>(); 

      for (int i = 1; i < vertices.Length; i++) 
      { 
       if (vertices.ContainsKey(vertices[i])) 
       { 
        indices.Add(vertices[i]); 
       } 
       if (vertices.ContainsKey(vertices[i - 1])) 
       { 
        indices.Add(vertices[i - 1]); 
       } 
       if (vertices.ContainsKey(vertices[middle])) 
       { 
        indices.Add(vertices[middle]); 
       } 
      } 

редактировать: если поиск в списке занимает 2 секунды, поиск в словаре займет 00:00:02 секунд

+2

обозначение «00: 00: 02» означает 2 секунды для меня, поэтому я понятия не имею, что «00:00: Предполагается, что должно означать 02 секунд. –

+0

означает, что это будет очень быстро –

+1

Это не помогает мне, потому что кажется, что в «ContainsKey (...)» мне нужно будет ввести ключ int, который представляет индекс, и если я уже как-то знал, что тогда это было бы необязательно ... – Gerharddc

0

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