Лучший способ отсортировать массив

Swift 4.1 У меня есть функция, которая просто передаёт URL-адрес изображения, кэш-ключ после создания изображения устанавливает его в блок завершения.

   class NetworkManager: NSObject {

  private var imageQueue = OperationQueue()
  private var imageCache = NSCache<AnyObject, AnyObject>()

  func downloadImageWithUrl(imageUrl: String, cacheKey: String, completionBlock: @escaping (_ image: UIImage?)-> Void) {

    let downloadedImage = imageCache.object(forKey: cacheKey as AnyObject)
    if let  _ = downloadedImage as? UIImage {
      completionBlock(downloadedImage as? UIImage)
    } else {
      let blockOperation = BlockOperation()
      blockOperation.addExecutionBlock({
        let url = URL(string: imageUrl)
        do {
          let data = try Data(contentsOf: url!)
          let newImage = UIImage(data: data)
          if newImage != nil {
            self.imageCache.setObject(newImage!, forKey: cacheKey as AnyObject)
            self.runOnMainThread {
              completionBlock(newImage)
            }
          } else {
            completionBlock(nil)
          }
        } catch {
          completionBlock(nil)
        }
      })
      self.imageQueue.addOperation(blockOperation)
      blockOperation.completionBlock = {
        print("Image downloaded \(cacheKey)")
      }
    }
  }
}
extension NetworkManager {
  fileprivate func runOnMainThread(block:@escaping ()->Void) {
    if Thread.isMainThread {
      block()
    } else {
      let mainQueue = OperationQueue.main
      mainQueue.addOperation({
        block()
      })
    }
  }
}
32
задан menjaraz 10 March 2012 в 10:39
поделиться

7 ответов

Можно добавить указатели на элементы массива к TList, затем звонить TList.Sort с функцией сравнения, и наконец создать новый массив и скопировать значения из TList в желаемом порядке.

Однако при использовании следующей версии, D2009, существует новая библиотека наборов, которая может отсортировать массивы. Это берет дополнительное IComparer<TExample> реализация для пользовательских порядков сортировки. Здесь это в действии для Вашего конкретного случая:

TArray.Sort<TExample>(SomeVar , TDelegatedComparer<TExample>.Construct(
  function(const Left, Right: TExample): Integer
  begin
    Result := TComparer<Integer>.Default.Compare(Left.SortOrder, Right.SortOrder);
  end));
36
ответ дан 27 November 2019 в 20:44
поделиться

Если Ваша потребность, отсортированная по строке затем, использует отсортированный TStringList и добавляет запись TString.AddObject(string, Pointer(int_val)).

, Но Если вид потребности целочисленным полем и строкой - использование TObjectList и после добавления всего вызова записей TObjectList.Sort с необходимыми отсортированными функциями как параметр.

3
ответ дан 27 November 2019 в 20:44
поделиться

Это все зависит от количества записей, которые Вы сортируете. Если Вы только сортируете меньше чем несколько сотен затем, другие методы сортировки хорошо работают, если Вы собираетесь быть сортировкой больше, то бросаете хороший взгляд на старое испытанное Турбо Питание проект SysTools. Существует очень хороший алгоритм сортировки, включенный в источник. Тот, который делает очень хорошую сортировку задания миллионы записей эффективным способом.

, Если Вы собираетесь использовать tStringList метод сортировки списка записей, удостоверьтесь, что Ваше целое число дополнено направо прежде, чем вставить его в список. Можно использовать формат (' %.10d', [rec.sortorder]) для выравнивания по правому краю к 10 цифрам, например.

2
ответ дан 27 November 2019 в 20:44
поделиться

С массивом я использовал бы или quicksort или возможно heapsort и просто изменил бы сравнение для использования TExample.SortOrder, часть подкачки все еще собирается просто действовать на указатели подкачки и массив. Если массив является очень большим затем, можно хотеть структуру связанного списка, если существует большая вставка и удаление.

C основывал стандартные программы, существуют несколько здесь http://www.yendor.com/programming/sort/

Другой сайт, но имеет источник Паскаля http://www.dcc.uchile.cl/~rbaeza/handbook/sort_a.html

1
ответ дан 27 November 2019 в 20:44
поделиться

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

0
ответ дан 27 November 2019 в 20:44
поделиться

TStringList имеют эффективный Метод сортировки.
, Если Вы хотите использование Вида TStringList объект с Sorted свойство к Истинному.

ПРИМЕЧАНИЕ: Для большей скорости включите объекты не Отсортированный TStringList, и в конце изменяют свойство на Истинный.
ПРИМЕЧАНИЕ: Для вида целочисленным Полем преобразуйте в Строку.
ПРИМЕЧАНИЕ: Если существуют дублирующиеся значения, этот метод не Действителен.

Отношения.

0
ответ дан 27 November 2019 в 20:44
поделиться

(Я знаю, что это год спустя, но все еще полезный материал.)

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

Вы начинаете с типа записи:

TExample = record
  SortOrder : integer;
  SomethingElse : string;
end;

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

var MyDA  Array of TExample; 
...
  SetLength(MyDA,NewSize);           //allocate memory for the dynamic array
  for i:=0 to NewSize-1 do begin        //fill the array with records
    MyDA[i].SortOrder := SomeInteger;
    MyDA[i].SomethingElse := SomeString;
  end;

Теперь вы хотите отсортировать этот массив по целочисленному значению SortOrder. Если вы хотите получить TStringList (чтобы вы могли использовать метод ts.Find), вам следует добавить каждую строку в список и добавить SortOrder в качестве указателя. Затем выполните сортировку по указателю:

var  tsExamples: TStringList;         //declare it somewhere (global or local)
...
  tsExamples := tStringList.create;   //allocate it somewhere (and free it later!)
...
  tsExamples.Clear;                   //now let's use it
  tsExamples.sorted := False;         //don't want to sort after every add
  tsExamples.Capacity := High(MyDA)+1 //don't want to increase size with every add
                                      //an empty dynamic array has High() = -1
  for i:=0 to High(MyDA) do begin
    tsExamples.AddObject(MyDA[i].SomethingElse,TObject(MyDA[i].SortOrder));
  end;

Обратите внимание на уловку преобразования Integer SortOrder в указатель TObject, который хранится в TStringList. Свойство объекта. (Это зависит от того, что Integer и Pointer имеют одинаковый размер.) Где-то мы должны определить функцию для сравнения указателей TObject:

function CompareObjects(ts:tStringList; Item1,Item2: integer): Integer;
var i,j: integer;
begin
  Result := integer(ts.Objects[i]) - integer(ts.Objects[j];
end;

Теперь мы можем отсортировать tsList на .Object, вызвав .CustomSort вместо .Sort ( который будет выполнять сортировку по строковому значению.)

tsExample.CustomSort(@CompareObjects);     //Sort the list

Список TStringList теперь отсортирован, поэтому вы можете перебирать его от 0 до .Count-1 и читать строки в отсортированном порядке.

Но предположим, что вам не нужен TStringList, а просто массив в отсортированном порядке. Или записи содержат больше данных, чем одна строка в этом примере, и ваш порядок сортировки более сложен. Вы можете пропустить этап добавления каждой строки и просто добавить индекс массива как элементы в TList. Сделайте все вышесказанное так же, за исключением того, что используйте TList вместо TStringList:

var Mlist: TList;                 //a list of Pointers
...
  for i:=0 to High(MyDA) do
    Mlist.add(Pointer(i));        //cast the array index as a Pointer
  Mlist.Sort(@CompareRecords);    //using the compare function below

function CompareRecords(Item1, Item2: Integer): Integer;
var i,j: integer;
begin
  i := integer(item1);            //recover the index into MyDA
  j := integer(item2);            // and use it to access any field
  Result := SomeFunctionOf(MyDA[i].SomeField) - SomeFunctionOf(MyDA[j].SomeField);
end;

Теперь, когда Mlist отсортирован, используйте его в качестве таблицы поиска для доступа к массиву в отсортированном порядке:

  for i:=0 to Mlist.Count-1 do begin
    Something := MyDA[integer(Mlist[i])].SomeField;
  end;

По мере того, как i перебирает TList, мы возвращаем индексы массива в отсортированном порядке. Нам просто нужно преобразовать их в целые числа, поскольку TList считает их указателями.

Мне нравится делать это таким образом, но вы также можете поместить настоящие указатели на элементы массива в TList, добавив адрес элемента массива вместо его индекса. Затем, чтобы использовать их, вы должны использовать их как указатели на записи TExample. Это то, что Барри Келли и CoolMagic сказали в своих ответах.

но вы также можете поместить настоящие указатели на элементы массива в TList, добавив адрес элемента массива вместо его индекса. Затем, чтобы использовать их, вы должны использовать их как указатели на записи TExample. Это то, что Барри Келли и CoolMagic сказали в своих ответах.

но вы также можете поместить реальные указатели на элементы массива в TList, добавив адрес элемента массива вместо его индекса. Затем, чтобы использовать их, вы должны использовать их как указатели на записи TExample. Это то, что Барри Келли и CoolMagic сказали в своих ответах.

12
ответ дан 27 November 2019 в 20:44
поделиться
Другие вопросы по тегам:

Похожие вопросы: