Remove duplicates from array of non-equatable objects
First note that there is no need to make the SearchResult properties (implicitly unwrapped) optionals, as they are always initialized:

class SearchResult { // non-equatable
    var index: Int
    var score: Int

    init(_ index: Int, score: Int = 0) {
        self.index = index
        self.score = score
    }
}


Your approach is indeed not optimal, after determining a unique set of property
values, the original array must be searched for each value separately. This lookup can be improved slightly by using first(where:) 

var noDupes: [SearchResult] = []
indices.forEach { (index) in
    guard let notADupe = withDupes.first(where: { $0.index == index }) else { return }
    noDupes.append(notADupe)
}


The advantage of first(where:) over filter + first is that it short-circuits and does not create an intermediate array.

But a better and faster solution would be to modify the removingDuplicates()
method so that it compares the array elements according to a given key (which is
then required to be Equatable).

Here is a possible implementation, using the “Smart KeyPath” feature
from Swift 4:

extension Array {
    func removingDuplicates&lt;T: Equatable&gt;(byKey key: KeyPath&lt;Element, T&gt;)  -&gt; [Element] {
        var result = [Element]()
        var seen = [T]()
        for value in self {
            let key = value[keyPath: key]
            if !seen.contains(key) {
                seen.append(key)
                result.append(value)
            }
        }
        return result
    }
}


This can then simply be used as

let searchResults: [SearchResult] = [SearchResult(0), SearchResult(1), SearchResult(1), SearchResult(2), SearchResult(2)]

let withoutDuplicates = searchResults.removingDuplicates(byKey: \.index)


It might also be worth to add another specialization for the case that the key is
Hashable (as it is in your example) because then the seen array can be replaced by a set,
which improves the lookup speed from O(N) to O(1):

extension Array {
    func removingDuplicates&lt;T: Hashable&gt;(byKey key: KeyPath&lt;Element, T&gt;)  -&gt; [Element] {
        var result = [Element]()
        var seen = Set&lt;T&gt;()
        for value in self {
            if seen.insert(value[keyPath: key]).inserted {
                result.append(value)
            }
        }
        return result
    }
}


Note that if seen.insert(key).inserted does the “test and insert if not present” with a single call.

Another (more flexible) option is to pass a closure to the function which determines
the uniquing key for each element:

extension Array {
    func removingDuplicates&lt;T: Hashable&gt;(byKey key: (Element) -&gt; T)  -&gt; [Element] {
        var result = [Element]()
        var seen = Set&lt;T&gt;()
        for value in self {
            if seen.insert(key(value)).inserted {
                result.append(value)
            }
        }
        return result
    }
}


Example:

let withoutDuplicates = searchResults.removingDuplicates(byKey: { $0.index })