2016-01-23 35 views
0

我有一个从另一个类更新的字典。我在字典上有一个属性观察者,所以我知道何时添加或删除了一个值。保持按索引更新字典值的有序数组

我创建了一个基于字典值的排序数组。我需要保持这个数组的更新,并保留与更新相关的索引,以便与UITableView一起使用。我的用户界面是这样的,批量重新加载数据是不可能的 - 我需要直接插入或删除基于更新的行。

我已经简化到这一个游乐场:

func dictionaryUpdated() { 

print("dictionary updated") 
// Add or remove string at index depending on order. 
} 

var myDictionary : [Int:String] = ["Bob".hashValue:"Bob","Dave".hashValue:"Dave","Yoda".hashValue:"Yoda","Windu".hashValue:"Windu","Obi Wan".hashValue:"Obi Wan","Qui-gon".hashValue:"Qui-gon","Anakin".hashValue:"Anakin"] { didSet { dictionaryUpdated() } } 

func addEntry(entry: String) { 

myDictionary[entry.hashValue] = entry 
} 

func removeEntry(entry: String) { 

myDictionary.removeValueForKey(entry.hashValue) 
} 

// sort the keys alphabetically while creating the array 
var valuesArray = myDictionary.values.sort { (lhs, rhs) -> Bool in 
return lhs < rhs 
} 

我已经使用NSMutableOrderedSet尝试,但密钥只能是字符串。

+0

有什么问题吗?您似乎找到了排序问题的解决方案,您是否遇到了该解决方案的一些问题? – Cristik

+0

@Cristik是 - 我需要保持数组更新属性观察员触发字典值已更改,我需要保留排序的更新的索引与UITableView一起使用。 –

+0

而且'valuesArray'没有办法吗?或者当字典内容改变时你有问题要检测吗? – Cristik

回答

1

只是在操场上玩耍。可以更优雅,但...

var valuesArray: [String] = [] { didSet { valuesArray.sortInPlace { $0 < $1 } } } 

func dictionaryUpdated(old: [Int: String]) { 

    let added = myDictionary.count > old.count 
    let item: [String] = added ? myDictionary.values.filter { !old.values.contains($0) } : old.values.filter { !myDictionary.values.contains($0) } 

    valuesArray += item 

    let index = valuesArray.indexOf(item[0])! 

    print("item " + (added ? "added" : "removed") + ": \(item) at index \(index)") 
} 

var myDictionary: [Int: String] = ["Yoda".hashValue: "Yoda", "Windu".hashValue: "Windu", "Obi Wan".hashValue: "Obi Wan"] { 
    didSet { 
     dictionaryUpdated(oldValue) 
    } 
} 

addEntry("Darth Vader") 
print(valuesArray) 

输出:

item added: ["Darth Vader"] at index 0 
["Darth Vader", "Obi Wan", "Windu", "Yoda"] 
+0

这个效果非常好,我添加了对添加的Bool的检查,如果它是false,我然后删除值数组上的项目,以便它可以用作tableview数据源。 –

+0

是的,我注意到它仍然需要一些工作,但你有想法;) –

0

假设你在属性改变之前和之后都有排序的数组(可以通过另一个实例变量来实现),你需要做的是比较旧数组和新数组,并检测哪些索引发生了变化。

这个问题的一个优雅的解决方案是将diff方法添加到计算差异的Array类中。该方法可能是这个样子:

extension Array where Element: Equatable { 
    func diff(other: [Element]) -> (added: [Int], deleted: [Int], moved: [(from: Int, to: Int)]) { 
     var added: [Int] = [] 
     var deleted: [Int] = [] 
     var moved: [(from: Int, to: Int)] = [] 
     for (i, item) in enumerate() { 
      if let j = other.indexOf({$0 == item}) { 
       if i != j { 
        moved.append((from: i, to: j)) 
       } 
      } else { 
       deleted.append(i) 
      } 
     } 
     for (i, item) in other.enumerate() { 
      if indexOf({$0 == item}) == nil { 
       added.append(i) 
      } 
     } 
     return (added: added, deleted: deleted, moved: moved) 
    } 
} 

这样,你会使用这样的:valuesArray.diff(oldValuesArray)