Swift: Merge Array of dictionaries with duplicate key but unique values - ios

I have a array of dictionaries which contains same key but different values. I want to merge these dictionaries and add all the values of same keys just like below:
var arrayofDict = [["2019":"A"],["2019":"B"],["2019":"C"],["2018":"A"],["2018":"c"],["2017":"A"],["2017":"B"],["2017":"C"],["2016":"A"],["2015":"A"],["2015":"B"]]
expected result as an Array like:
var newDict = [["2019":["A","B","C"]],["2018":["A","C"]],["2017":["A","B","C"]],["2016":["A"]],["2015":["A","B"]]]

This shows how to build a single dictionary. Your "expected result" is an array. Is this what you really expected or did you want an array?
You can iterate the dictionary items and build up the dictionary entries:
var arrayofDict = [["2019":"A"],["2019":"B"],["2019":"C"],["2018":"A"],["2018":"c"],["2017":"A"],["2017":"B"],["2017":"C"],["2016":"A"],["2015":"A"],["2015":"B"]]
var result = [String : [String]]()
for dict in arrayofDict {
for (key, value) in dict {
result[key, default: []].append(value)
}
}
print(result)
["2016": ["A"], "2018": ["A", "c"], "2015": ["A", "B"], "2019": ["A", "B", "C"], "2017": ["A", "B", "C"]]
Or, if you want an array:
let result2 = result.map { [$0.key: $0.value] }
print(result2)
[["2015": ["A", "B"]], ["2016": ["A"]], ["2019": ["A", "B", "C"]], ["2018": ["A", "c"]], ["2017": ["A", "B", "C"]]]

as #vacawama in more functional way
let result = arrayofDict.reduce(into: [String:[String]]()) { (acc, d) in
for key in d.keys {
// don't worry to force unwrap d[key], if key exist, the value is not nil
acc[key, default: []].append(d[key]!)
}
}

Related

How to sort a dictionary of [int: String] in Swift 5 [duplicate]

This question already has answers here:
Sort Dictionary by keys
(16 answers)
Closed 3 years ago.
I have an array that has integers as keys, and strings for values
var dictionary = [Int: String]()
All of these try's either end in compile error for Swift 5:
dictionary = dictionary.keys.sorted()
dictionary = (dictionary.sorted{ $0.key < $1.key })
dictionary = dictionary.sorted { $0.0 < $1.0 } .map { $0.1 }
reverseSortedValues = dictionary.sorted { $0.0 > $1.0 } .map { $0.1 }
dictionary = profileImagesDictionary.sorted(by: { $0.0.compare($1.0) == .OrderedAscending })
dictionary = profileImagesDictionary.sorted { $0.key
Code:
profileImagesDictionary = [Int : String](uniqueKeysWithValues: profileImagesDictionary.sorted{ $0.key > $1.key})
Console Output printed keys
before: dictionary = [3, 1, 2, 4, 0]
after: dictionary = [3, 0, 2, 1, 4]
I need it to rearrange the dictionary / actually sort it by keys.
So like instead of:
dictionary = [1: "a", 3: "c", 2: "b"]
It after being sorted would be:
dictionary = [1: "a", 2: "b", 3: "c"]
Simply give the following code to print sorted keys.
print(dictionary.keys.sorted)
Here you have a Dictionary not an Array, to sort your dictionary based on your keys you could use let sortedKeys = Array(dictionary.keys).sort(<) , but it only contains keys in array

Swift array map with comma before append new value

i have this following data structure in my Realm object
var tags = List<Tag>()
"tags": [
{
"tagId": "80069",
"tagName": "A"
},
{
"tagId": "80070",
"tagName": "B"
},
{
"tagId": "80071",
"tagName": "C"
},
{
"tagId": "80073",
"tagName": "D"
}
]
So what i want to achieve is, I map all my tag name into my new array
this is my code
let realmObject = self.realm.objects(MyDTO.self)
let array = Array(realmOutletList).map{Array($0.tags).map{$0.tagName!}.joined(separator: ",")}
it prints out this
["A,B,C", "A,C,D", "B,C,D"]
What I want to achieve is like
["A","B","C", "A","C","D", "B","C","D"]
I need that kind of array because I am going to create a Set from the array and then compare with another array
The compared array will be like
["A","B","C", "A","C","D", "B","C","D"]
because of the compared Array and the realmObject Array is different, it always shows false when i use
let subset = filterSet.isSubset(of: mySet)
Can anyone guide me please??
Thanks
Let's walk through solving the issue:
Consider that you have:
let originalArray = ["A,B,C", "A,C,D", "B,C,D"]
First, we need to separate each string in originalArray by "," character, so we could do:
let modifiedArray = originalArray.map { $0.components(separatedBy: ",") }
We map it to transform each string to a strings array (separation).
So far, the output of modifiedArray would be:
[["A", "B", "C"], ["A", "C", "D"], ["B", "C", "D"]]
which is an array of strings array.
Second, we need to spilt each -string- array in modifiedArray (having one reduced strings array instead), so we could do:
var final = [String]()
for array in modifiedArray {
for string in array {
final.append(string)
}
}
OR by using reduce
let finalArray = modifiedArray.reduce([], +)
Therefore, finalArray would be:
["A", "B", "C", "A", "C", "D", "B", "C", "D"]
which is the desired result.
Conclusion
For a fully one-lined answer (following the high-order functions approach):
let originalArray = ["A,B,C", "A,C,D", "B,C,D"]
let desiredArray = originalArray.map { $0.components(separatedBy: ",") }.reduce([], +)
print(desiredArray) // ["A", "B", "C", "A", "C", "D", "B", "C", "D"]
Well, it's quite easy:
This
let array = Array(realmOutletList).map{Array($0.tags).map{$0.tagName!}.joined(separator: ",")}
should be this
let array = Array(realmOutletList).flatMap{Array($0.tags).map{$0.tagName!}}
That's all. And you will get your ["A","B","C", "A","C","D", "B","C","D"].

How do I sort an array of dictionary according to an array contents in Swift

I have an array of dictionary. I need to sort that array. The sorting shouldnt be like ascending or descending but it should be based on an another array contents.
EX: Lets say I have an array nammed array_unsorted and that array contains a lot of dictionary objects like d1, d2, d3, d4 etc. Each of the dictionary object has a key called key1 and each dictionary object has different value for that key such as Kammy, Maddy, Jessy. Lets say I have anohter sorted array which Maddy, Kammy, Jessy. Now the dictionary should be sorted in a way that the first element should the dictionary object in which the value for key1 should beMaddy`.
I cannot use SortDescriptor, because this will sort as an ascending or descending order based on the key passed to it.
I have tried my solution but I am ended up using so many nested loops. I feel like the solution I made so so pathetic that I dont even want to post the code here.
Any help would be so much appreciated.
EDIT: There can be multiple sorting arrays but as of now I am considering only one sorting array and then I can write the code for multiple sorting arrays.
How about this:
Create a new, empty dictionary with a String key, and a value of type Dictionary. Call it sourceItemsDict.
Loop through the dictionaries in your source array, and add each entry to your new dictionary, using your sort key as the dictionary key, and put the array entry as the value.
Create a new, empty array of dictionaries for your sorted results. call it sortedArray.
Now loop through your array that has the desired order in it. Fetch the item with that key from sourceItemsDict and append it to the end of sortedArray.
That should do it, and it should perform in O(n) time.
Try this:
func sort<T: Equatable>(arrayOfDict arr: [[String: T]], by key: String, order: [T]) -> [[String: T]] {
return arr.sorted {
guard let value0 = $0[key], let value1 = $1[key] else {
return false
}
guard let index0 = order.index(of: value0), let index1 = order.index(of: value1) else {
return false
}
return index0 < index1
}
}
let array_unsorted = [
["name": "Kammy", "city": "New York"],
["name": "Maddy", "city": "Cupertino"],
["name": "Jessy", "city": "Mountain View"]
]
let sortedByName = sort(arrayOfDict: array_unsorted, by: "name", order: ["Maddy", "Kammy", "Jessy"])
let sortedByCity = sort(arrayOfDict: array_unsorted, by: "city", order: ["Cupertino", "Mountain View", "New York"])
print(sortedByName)
print(sortedByCity)
Your question leaves a couple of unresolved scenarios:
1: What if the key is missing from a dictionary?
let array_unsorted = [
["name": "Kammy", "city": "New York"],
["city": "Las Vegas"],
["name": "Maddy", "city": "Cupertino"],
["name": "Jessy", "city": "Mountain View"]
]
let sortedByName = sort(arrayOfDict: array_unsorted, by: "name", order: ["Maddy", "Kammy", "Jessy"])
Should Las Vegas appear at the beginning or end of the sorted array?
2: What if you don't specify an order for a value?
let array_unsorted = [
["name": "Amy"],
["name": "Kammy", "city": "New York"],
["name": "Maddy", "city": "Cupertino"],
["name": "Jessy", "city": "Mountain View"]
]
let sortedByName = sort(arrayOfDict: array_unsorted, by: "name", order: ["Maddy", "Kammy", "Jessy"])
Now where should Amy be placed?
Check out this example:
let dic1 = ["name" : "a"]
let dic2 = ["name" : "b"]
let dic3 = ["name" : "c"]
let dic4 = ["name" : "d"]
let dic5 = ["name" : "e"]
let unsorted_array = [dic2,dic5,dic1,dic4,dic3]
func sortArrayByName(_ array:[[String:String]])->[[String:String]]{
var sortedArray:[[String:String]] = [[String:String]]()
var sortingOrder:[String] = [String]()
for eachDic in array{
if let name = eachDic["name"]{
sortingOrder.append(name)
sortingOrder.sort() // sorting logic here
if sortedArray.isEmpty{
sortedArray.append(eachDic)
} else {
let index = sortingOrder.index(of: name)!
sortedArray.insert(eachDic, at: index)
}
}
}
return sortedArray
}
let sorted_array = sortArrayByName(unsorted_array)

How to add element at Last index Swift

I am getting an Array from server and I store it in NSMutableArray. Now the issue is that the Array is not sorted. For eg. array = ["A","B","None","C","D"]. I want to sort it and place the "None" element at last. i.e ["A","B","C","D","None"]. Tried swapping but was unable to match the condition, as the array may increase in future. Check my code below which is not working as expected.
if array.containsObject( "None" ){
print("\(array.indexOfObject("None"))")
let noneIndex = array.indexOfObject("None")
print(noneIndex)
array.removeObject(noneIndex)
print("Remove Array:-\(array)")
array.insertObject(noneIndex, atIndex: (array.lastObject?.index)!)
print("Sorted Array:-\(array)")
}
Maybe I'm misunderstanding what it is that you need to do, but you could use sorted() on your array if you just want to sort it alphabetically.
You could also use filter to remove "None" from your array, sort it, and then append "None" as the last element
For instance, if you have
let elements = ["Alpha", "Bold", "None", "charlie", "Delta", "echo", "zebra", "k"]
You could start out by filtering it:
let filteredElements = elements.filter { $0.uppercased() != "NONE"}
Sort the filtered elements:
var sortedElements = filteredElements.sorted { $0.uppercased() < $1.uppercased()}
Append "None"
sortedElements.append("None") // ["Alpha", "Bold", "charlie", "Delta", "echo", "k", "zebra", "None"]
And be done.
Here it is combined:
let lastElement = "None"
let elements = ["Alpha", "Bold", "None", "charlie", "Delta", "echo", "zebra", "k"]
var sortedElements = elements.filter({$0.uppercased() != lastElement.uppercased()}).sorted(by: {$0.uppercased() < $1.uppercased()})
sortedElements.append(lastElement)
Hope that helps you.
var array = ["A", "B", "None", "C", "D"]
if let noneIndex = array.index(of: "None") {
array.remove(at: noneIndex)
array.append("None")
}
print(array)
This should move None at the end of the array, and sort the other elements:
let ["A", "B", "None", "C", "D"]
array.sorted { $1 == "None" || $0 < $1 } // ["A", "B", "C", "D", "None"]
This simply takes benefits of the by argument that can be passed to the sort/sorted method from Array.
Edit #MartinR had a very strong point regarding the comparison predicate from this answer, which indeed doesn't offer a strong weak ordering. Sorting the array with a correct predicate would be along the lines of:
array.sorted { $0 == "None" ? false : $1 == "None" ? true : $0 < $1 }
This will work:
// starting test array
let array = ["B", "None", "C","P","None","A", "Q"]
var sorted = array.sorted { (str1, str2) -> Bool in
return str1 < str2
}
sorted.forEach { str in
if str == "None" {
if let idx = sorted.index(of: str) {
sorted.remove(at: idx)
sorted.append(str)
}
}
}
// Sorted array is now ["A", "B", "C", "P", "Q", "None", "None"]

Get all keys of nsdictionary sorted alphabetically in swift?

I have got a NSDictionary with alphabets as keys. I want to get those keys sorted alphabetically . I have tried many methods but I am getting error on Sort() method. Can any one help me ????
Thanks in advance
Note:
1) I don't want to get a sorted array of dictionaries
2) I don't want to sort the dictionary by means of the values
(I am getting a lot of answers for this )
You can sort the keys this way:
let dictionary: NSDictionary = ["a" : 1, "b" : 2]
let sortedKeys = (dictionary.allKeys as! [String]).sorted(<) // ["a", "b"]
Swift 3:
let dictionary: NSDictionary = ["a" : 1, "b" : 2]
let sortedKeys = (dictionary.allKeys as! [String]).sorted(by: <) // ["a", "b"]
In Swift 2.2
You can sort like this in Ascending Order
let myDictionary: Dictionary = ["a" : 1, "b" : 2]
let sortedKeys = myDictionary.keys.sort() // ["a", "b"]
Descending Order
let myDictionary: Dictionary = ["a" : 1, "b" : 2]
let sortedKeys = myDictionary.keys.sort(>) // ["b", "a"]
For Swift 3
// Initialize the Dictionary
let dict = ["name": "John", "surname": "Doe"]
// Get array of keys
var keys = Array(dict.keys).sorted(by: >)
print(keys)

Resources