Использование Block sortedArrayUsingComparator:^(id a, id b)

В моем проекте я пытаюсь сравнить известное местоположение с введенным местоположением, используя блок sortedArrayUsingComparator:^(id a, id b). У меня есть массив словарей с именем locationArray, содержащий длинную широту и номер станции, соответствующий этой длинной точке. Я пытаюсь сравнить каждую станцию ​​locationArray с введенной станцией. Я делаю это, взяв абсолютное значение разницы между ними, что дает мне расстояние. Затем я пытаюсь отсортировать locationArray на основе расстояния от введенной станции от ближайшей до самой дальней.

//locationArray

#define kStation @"station"
#define kLatitude @"latitude"
#define kLongitude @"longitude"




NSString *filePath = [[NSBundle mainBundle] pathForResource:@"499CSV" ofType:@"csv"];
NSString *csvString = [NSString stringWithContentsOfFile:filePath  encoding:NSUTF8StringEncoding error:nil];

NSArray *locations = [csvString componentsSeparatedByCharactersInSet:[NSCharacterSet newlineCharacterSet]];

NSMutableArray *CSVArray = [NSMutableArray array];


NSCharacterSet *whiteSPNewLine = [NSCharacterSet whitespaceAndNewlineCharacterSet];
for (NSString * location in locations)
{

NSArray *components = [location componentsSeparatedByString:@","];

double latitude   = [[components[0] stringByTrimmingCharactersInSet:whiteSPNewLine] doubleValue];
double longitude  = [[components[1] stringByTrimmingCharactersInSet:whiteSPNewLine] doubleValue];
NSString *station = [components[2] stringByTrimmingCharactersInSet:whiteSPNewLine];

NSDictionary *dict = @{kLatitude: @(latitude),
                       kLongitude: @(longitude),
                       kStation: station};

[CSVArray addObject:dict];

}

NSLog(@"The contents of CSVArray = %@",[CSVArray description]);


{
    latitude = "41.674364";
    longitude = "-81.23700700000001";
    station = 40150;
},
    {
    latitude = "41.67517";
    longitude = "-81.235038";
    station = 40763;
},
    {
    latitude = "41.673106";
    longitude = "-81.24017499999999";
    station = 39175;
}, ...

Мой блочный код, который следует непосредственно за locationArray.

NSArray *orderedPlaces = [CSVArray sortedArrayUsingComparator:^(id a, id b) {

NSDictionary *dictA;
NSDictionary *dictB;

NSString *locA;
NSString *locB;

int distanceA;
int distanceB;


dictA = (NSDictionary *)a;
dictB = (NSDictionary *)b;

NSLog(@"dictA = %@", dictA);
NSLog(@"dictB = %@", dictB);


locA = [dictA objectForKey:kStation];
locB = [dictB objectForKey:kStation];

NSLog(@"locA = %@", locA);
NSLog(@"locB = %@", locB);



distanceA = abs(stationNumber-[locA intValue]);
distanceB = abs(stationNumber-[locB intValue]);

NSLog(@"distanceA = %d", distanceA);
NSLog(@"distanceB = %d", distanceB);

if (distanceA < distanceB) {
  return NSOrderedAscending;
} else if (distanceA > distanceB) {
  return NSOrderedDescending;
} else {
  return NSOrderedSame;
}


}];

NSLog(@"The contents of array = %@",[orderedPlaces description]);

Блок запускается, но не сортирует, как предполагалось, locationArray. orderedPlaces возвращает несортированный массив LocationsArray. Запустив NSLOG для блочных компонентов, я вижу, что он успешно распознает locationArray и создает объект расстояния. Я должен что-то упустить, потому что я использую тот же код в другой части моего проекта, где я сравниваю LocationArray с долготой долготы местоположения пользователя, и он работает хорошо. Пожалуйста, помогите мне определить проблему, из-за которой он не работает должным образом.

* Если вам нужна дополнительная информация или разъяснения, просто спросите.


person user2621075    schedule 20.09.2013    source источник


Ответы (2)


Я не понимаю ваш блок сортировки. Вы рассчитываете расстояние A как abs(stationNumber-[locA intValue]).

Что такое номер станции? Это какой-то фиксированный целочисленный индекс? Как разница между фиксированным номером станции и номерами станций в вашем массиве может быть связана с расстоянием?

Мне кажется, что ваши значения расстояния должны быть (target.lat - this_station.lat)^2 + (target.long - this_station.long)^2

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

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

person Duncan C    schedule 21.09.2013
comment
Номер станции — это точная точка на схеме проезжей части, поэтому, например, станция 10000 находится в 100 футах от станции 10100. Единственный объект словаря, который меня действительно волнует, - это тот, чья станция находится ближе всего к введенной станции, и я хочу, чтобы этот объект словаря был первым (objectAtIndex:0) объектом в упорядоченном массиве. Я использую значение расстояния, чтобы сравнить близость от введенной станции ко всем станциям в locationArray, поэтому ближайшей будет та, у которой кратчайшее расстояние. Значение abs гарантирует, что большие отрицательные числа не будут ошибочно приняты за самые близкие. - person user2621075; 21.09.2013

Попробуй это:

NSArray *orderedPlaces = [CSVArray sortedArrayUsingComparator:^NSComparisonResult(id a, id b) {

^(id a, id b) означает ^void (id a, id b), и возвращаемое вами значение игнорируется.

person sofacoder    schedule 22.09.2013
comment
^(id a, id b) означает ^void (id a, id b) Нет, это не так. Тип возвращаемого значения предполагается. - person newacct; 23.09.2013
comment
Вот так. Из clang.llvm.org/docs/BlockLanguageSpec.html: тип возвращаемого значения является необязательным. и выводится из операторов return. Если операторы return возвращают значение, все они должны возвращать значение одного и того же типа. Если значение не возвращается, предполагаемый тип блока является недействительным; в противном случае это тип значения оператора return. - person sofacoder; 23.09.2013