2

配列メソッドがわかりませんindexOfObject:inSortedRange:options:usingComparator:

より具体的には、indexOfObjectプロパティ。

ドキュメントによると、渡された値は次のようになるはずですがAn object for which to search in the array. 、これは意味がありません..オブジェクトへの参照が既にある場合、なぜ配列でそれを検索するのでしょうか? それはオブジェクトタイプを意味しますか?

私はオブジェクトの配列を持っていますが、私が持っているのはそれらのオブジェクトのプロパティだけです。すなわち。車の配列があり、車の ID が 12345 のときに車のオブジェクトを見つける必要があります。

indexOfObjectプロパティのメソッドに何を渡しますか? ここに私がしようとしているものがあります

   MyCarObject *searchObject;
   NSUInteger findIndex = [sortedArray indexOfObject:searchObject
                                       inSortedRange:searchRange
                                             options:NSBinarySearchingFirstEqual
                                     usingComparator:^(id obj1, id obj2)
                              {
                                return [obj1 compare:obj2];
                              }];

しかし、これは明らかにIDに基づいてオブジェクトを取得するつもりはありません..私がすでに参照しているプロパティのインデックスを私に与えるように見えますが、これは無意味に思えます....

これが正しい方法ではない場合、何を使用すればよいですか? オブジェクトの配列に対してバイナリ検索を使用し、そのオブジェクトへの参照を引き出す必要があります。そして、私が持っているのは比較するプロパティだけです。

4

4 に答える 4

2

このメソッドは、特定の配列内のオブジェクトのインデックスを返します。これは、場合によっては非常に便利です。配列内のオブジェクトは、isEqual:メソッドを使用して比較されます (デフォルトではポインターが比較されます)。これが、いくつかのカスタム プロパティを使用してメソッドを比較する必要があることをメソッドが知る機会がない理由です。

独自のプロパティで配列内の特定のオブジェクトを見つけるには、使用できます

  • NSArrays メソッド- (NSArray *)filteredArrayUsingPredicate:と対応するNSPredicate(SO とこれらのチュートリアルに関する多くの質問があります)
  • 必要なプロパティを任意の値と比較する独自のループ (この場合、車を検索する ID を持つオブジェクトの車の ID)
于 2013-09-24T14:26:21.213 に答える
1

私はこの方法を実際に推奨するわけではありませんが、この API を叩いてやりたいことを実行させることは可能です。検索したいキーを渡すと、比較対象の要素とともにコンパレータに渡されます。ただし、これらの引数が渡される順序は変更されるため、それらを区別して比較を実行するには、実行時にコンパレータ引数のクラスを検査する必要があります。

- (BWCProductCategory *)categoryForID:(NSNumber *)ID categories:(NSArray *)categories {
    NSRange searchRange = NSMakeRange(0, categories.count);
    NSUInteger index = [categories indexOfObject:ID
                                   inSortedRange:searchRange
                                         options:NSBinarySearchingFirstEqual
                                 usingComparator:^NSComparisonResult(id obj1, id obj2) {
                                     if ([obj1 isKindOfClass:[BWCProductCategory class]]) {
                                         return [[(BWCProductCategory *)obj1 categoryID] compare:obj2];
                                     } else {
                                         return [obj1 compare:[(BWCProductCategory *)obj2 categoryID]];
                                     }
                                 }];

    return (index == NSNotFound) ? nil : categories[index];
}

これは機能しますが、かなりぎこちなく感じます。また、大規模な検索を実行したときのパフォーマンスへの影響については確信が持てません (ただし、それでも O(n) 検索よりも少ないことは確かです)。おそらく、クラッジ要因を隠すこれらの上に、より良い方法を構築できます。

于 2014-03-18T13:54:45.863 に答える
0

Arrayこの方法での Swift の使用を非常にクリーンにするために、Swift の拡張機能を作成しました。

import Foundation

extension Array where Element: AnyObject {

    public func indexOfObject<T: AnyObject>(obj: T, options opts: NSBinarySearchingOptions, usingComparator cmp: (T, Element) -> NSComparisonResult) -> Int {
        return (self as NSArray).indexOfObject(obj, inSortedRange: NSRange(0..<count), options: opts, usingComparator: { (a: AnyObject, b: AnyObject) -> NSComparisonResult in
            if a === obj {
                return cmp(a as! T, b as! Element)
            } else {
                var result = cmp(b as! T, a as! Element)

                if result == .OrderedDescending {
                    result = .OrderedAscending
                } else if result == .OrderedAscending {
                    result = .OrderedDescending
                }

                return result
            }
        })
    }
}

使用例を次に示します。

class ItemWithProperty {
    var property: Int

    init(property: Int) {
        self.property = property
    }
}

let listOfItems = [ItemWithProperty(property: 1),
    ItemWithProperty(property: 20),
    ItemWithProperty(property: 30),
    ItemWithProperty(property: 45),
    ItemWithProperty(property: 45),
    ItemWithProperty(property: 45),
    ItemWithProperty(property: 60),
    ItemWithProperty(property: 77),
]

let indexOf20 = listOfItems.indexOfObject(20, options: .FirstEqual) { number, item in
    number.compare(item.property)
}
// returns 1

let indexOf25 = listOfItems.indexOfObject(25, options: .FirstEqual) { number, item in
    number.compare(item.property)
}
indexOf25 == NSNotFound
// comparison is true, number not found

let indexOfFirst45 = listOfItems.indexOfObject(45, options: .FirstEqual) { number, item in
    number.compare(item.property)
}
// returns 3

let indexOfLast45 = listOfItems.indexOfObject(45, options: .LastEqual) { number, item in
    number.compare(item.property)
}
// returns 5

let indexOf77 = listOfItems.indexOfObject(77, options: .FirstEqual) { number, item in
    number.compare(item.property)
}
// returns 7
于 2015-10-15T15:23:30.760 に答える
0

メソッド(compare:バイナリ検索コンパレータに使用している)は、オブジェクトに応じて異なることを意味します。NSStringたとえば、字句比較として比較を実装します。したがって、並べ替えられた がある場合、NSArray返さNSStringれるのは、入力文字列に一致する文字列のリスト内のインデックスです (またはNSNotFound配列内にない場合)。

オブジェクト タイプ ( MyCarObject) の場合、 の定義を実装してcompare:、 の相対的な順序を決定しますMyCarObject。次に、 の新しいインスタンスを構築し、MyCarObjectこのメソッドを使用して、同等のオブジェクト ( によって決定されるcompare:) がリストに既に存在するかどうかを判断します。

このメソッドはバイナリ検索を行うため、検索に使用しているのと同じコンパレータを使用して配列をソートしておく必要があることに注意してください。NSBinarySearchingInsertionIndexリストをソートしたままにするために、新しい要素を挿入するインデックスを見つけるために使用できます。

于 2016-01-13T15:32:09.413 に答える