2016-06-02 8 views
2

Gegeben ist ein Array, das aus Arrays besteht, die Ganzzahlen enthalten.Entfernen der kleineren Sätze von Werten aus einem Array von Arrays in Swift

[[2], [3], [2, 2], [5], [7], [2, 2, 2], [3, 3]] 

Was die bevorzugte Art und Weise in Swift würde die Arrays zu entfernen, die eine kleinere Anzahl von Elementen mit einem bestimmten Wert enthält und hält nur die größere Arrays, den Wert enthält.

Das Ergebnis von der Eingabe würde über

[[5], [7], [2, 2, 2], [3, 3]] 
+0

Sie werden präziser sein. Möchten Sie, dass dies stabil ist (unter Beibehaltung der ursprünglichen Reihenfolge), was sollte mit Duplikaten geschehen? Ich nehme an, dass Sie nur Arrays mit der höchsten Anzahl übrig haben wollen. – ColGraff

+0

Die Reihenfolge spielt keine Rolle, ich habe meine Frage bearbeitet, um sie klarer zu machen. Ja, nur die Arrays mit der höchsten Anzahl. – JKT

Antwort

2

einen [Int: [Int]] Wörterbuch Nutzen seine Spur des größten Array durch den Schlüssel für den angegebenen Wert zu halten.

let arrays = [[2], [3], [2, 2], [5], [7], [2, 2, 2], [3, 3]] 
var largest = [Int: [Int]]() 

for arr in arrays { 
    // Get the first value from the array 
    if let first = arr.first { 

     // current is the count for that key already in dictionary largest 
     // If the key isn't found, the nil coalescing operator ?? will 
     // return the default count of 0. 
     let current = largest[first]?.count ?? 0 

     // If our new array has a larger count, put it in the dictionary 
     if arr.count > current { 
      largest[first] = arr 
     } 
    } 
} 

// Convert the dictionary's values to an array for the final answer. 
let result = Array(largest.values) 

print(result) // [[5], [7], [2, 2, 2], [3, 3]] 

Dieselbe Logik mit reduce verwendet werden kann, um das Ergebnis in einer Zeile zu bieten:

let result = arrays.reduce([Int: [Int]]()) { var d = $0; guard let f = $1.first else { return d }; d[f] = d[f]?.count > $1.count ? d[f] : $1; return d }.map { $1 } 

Andere Version

Diese Version verwendet ein [Int: Int] Wörterbuch um nur die Anzahl zu halten das größte Array, das für jeden Schlüssel gefunden wurde, und rekonstruiert dann die Arrays am Ende mithilfe eines Array-Konstruktors.

let arrays = [[2], [3], [2, 2], [5], [7], [2, 2, 2], [3, 3]] 
var counts = [Int: Int]() 

for arr in arrays { 
    if let first = arr.first { 
     counts[first] = max(counts[first] ?? 0, arr.count) 
    } 
} 

let result = counts.map { [Int](count: $1, repeatedValue: $0) } 

print(result) // [[5], [7], [2, 2, 2], [3, 3]] 

Dieselbe Logik kann mit reduce verwendet werden, um das Ergebnis in einer Zeile zu bieten:

let result = arrays.reduce([Int: Int]()) { var d = $0; guard let f = $1.first else { return d }; d[f] = max(d[f] ?? 0, $1.count); return d }.map { [Int](count: $1, repeatedValue: $0) } 
1

ich meine Antwort gerade dabei war, zu schreiben, wenn ich, dass vacawama sah mit reagiert hatte etwas sehr ähnliches. Entschieden, um wieder zu kommen, nur weil es ein interessantes Problem ist, um damit herumzuspielen. Also ist meine Alternative mit ziemlicher Sicherheit viel langsamer als die Lösungen von vacawama und bewahrt nicht die Reihenfolge, aber ich fand es interessant als Beispiel für die Alternativen, die Sie haben, um solche Probleme in Swift zu lösen.

var items = [[2], [3], [2, 2], [5], [7], [2, 2, 2], [3, 3]] 

let reduced = items.sort({ 
     let lhs = $0.first, rhs = $1.first 
     return lhs == rhs ? $0.count > $1.count : lhs < rhs 
    }).reduce([[Int]]()) { (res, items) in 
     return res.last?.last != items.last ? res + [items] : res 
    } 

print(reduced) // [[2, 2, 2], [3, 3], [5], [7]] 

Oder wenn Sie lieber, dass alles auf einer einzigen Zeile stopfen würde:

var items = [[2], [3], [2, 2], [5], [7], [2, 2, 2], [3, 3]] 

let reduced = items.sort({ let lhs = $0.first, rhs = $1.first; return lhs == rhs ? $0.count > $1.count : lhs < rhs }).reduce([[Int]]()) { $0.last?.last != $1.last ? $0 + [$1] : $0 } 

print(reduced) // [[2, 2, 2], [3, 3], [5], [7]] 
0

nur eine Alternative mit forEach:

let arrays = [[2], [2, 2], [5], [7], [2, 2, 2], [3, 3], [3]] 
var largest: [Int: [Int]] = [:] 

arrays.forEach({ 
    guard let first = $0.first else { return } 
    largest[first] = [Int](count: max($0.count,largest[first]?.count ?? 0), repeatedValue: first) 
}) 
Array(largest.values) // [[5], [7], [2, 2, 2], [3, 3]] 
Verwandte Themen