I 'm having an array of dictionary like so...
[
{
"id" : "3",
"sellingPrice" : "520",
"quantity" : "15"
},
{
"id" : "5",
"sellingPrice" : "499",
"quantity" : "-1"
},
{
"id" : "8",
"sellingPrice" : "500",
"quantity" : "79"
}
]
Now I want to add to the dictionary another key called remaining_balance with a value of 420,499 & 500 respectively. How can I achieve this..? Hope somebody can help...
It seems like you want to add a value to your dictionary that is an array:
var arrDict = Array<Dictionary<String,Any>>() //Your array
arrDict.append(["id":"3","sellingPrice":"520","quantity":"13"])
arrDict.append(["id":"5","sellingPrice":"43","quantity":"32"])
arrDict.append(["id":"8","sellingPrice":"43","quantity":"33"])
let arrValue = ["420","499","500"] //Your remaining value in array
print("Before ",arrDict)
for (index,dict) in arrDict.enumerated() {
var dictCopy = dict //assign to var variable
dictCopy["remaining_balance"] = arrValue[index]
arrDict[index] = dictCopy //Replace at index with new dictionary
}
print("After ",arrDict)
EDIT
If you are able keep an index of an array it would be possible,
Assuming that you have the index of an array
var dictCopy = arrDict[index]
dictCopy["remaining_balance"] = "666" //Your calculated value
arrDict[index] = dictCopy //Replace at index with new dictionary
var newKV = [["remaining_balance": "420"],["remaining_balance": "490"],["remaining_balance": "500"]]
let array = [["id":"3", "sellingPrice":"520", "quantity":"15"], ["id":"5", "sellingPrice":"520", "quantity":"15"], ["id":"8", "sellingPrice":"520", "quantity":"15"]]
let newArray = array.enumerated().map { (index : Int, value: [String: String]) -> [String: String] in
var dic = value
dic.merge(newKV[index]) { (_, new) -> String in
new
}
return dic
}
You could achieve it by mapping your array:
var myArray = [["id": "3", "sellingPrice": "520", "quantity" : "15"], ["id": "5", "sellingPrice": "499", "quantity" : "-1"], ["id": "8", "sellingPrice": "500", "quantity" : "79"]]
print(myArray)
/*
[["id": "3", "sellingPrice": "520", "quantity": "15"],
["id": "5", "sellingPrice": "499", "quantity": "-1"],
["id": "8", "sellingPrice": "500", "quantity": "79"]]
*/
print("___________________")
var remainingBalanceDesriedValue = 420
myArray = myArray.map { (dict: [String: String]) -> [String: String] in
var copyDict = dict
copyDict["remaining_balance"] = "\(remainingBalanceDesriedValue)"
remainingBalanceDesriedValue = (remainingBalanceDesriedValue == 420) ? 499 : (remainingBalanceDesriedValue == 499) ? 500 : 420
return copyDict
}
print(myArray)
/*
[["sellingPrice": "520", "quantity": "15", "id": "3", "remaining_balance": "420"],
["sellingPrice": "499", "quantity": "-1", "id": "5", "remaining_balance": "499"],
["sellingPrice": "500", "quantity": "79", "id": "8", "remaining_balance": "500"]]
*/
Let's assume you have an array of dictionaries like so:
var arrayOfDictionaries = [
[
"id": 3,
"sellingPrice": 520,
"quantity": 15
]
]
It is important that arrayOfDictionaries is not a let constant, otherwise it is considered immutable and you can not call append on it.
Now you init a new dictionary like:
let newDictionary = [
"id": 10,
"remaining_balance": 420,
"quantity": 15
]
Now add the newDictionary like
arrayOfDictionaries.append(newDictionary)
If the order is important
If the order is important there are a couple of ways to go about that.
When calling append the new value (in this case the new dictionary) will always be inserted at the bottom of the array.
If for some reason you can not call append in the correct order you could use insert, which inserts your dictionary at a specific position.
Yet another way is to append the values wildly and after you are done, call sort on the array.
Improvement Tips
Notice that for the values I did not use strings, as you only have numbers like "id" : 30.
Also, if you want the second key to be called remaining_balance you should call the first key selling_price instead of sellingPrice. Because of conistency.
Alternative approach
As far as I have understood you are trying to implement some software that is responsibly for selling some products.
I think you are tackling this problem from a completely wrong side.
I think you should read about database relationships. Selling products actually is a very common problem.
Maybe this will help you. I would offer a possible solution myself, but I think this misses the point of your question.
If you decide to use the database approach, you won't necessarily have to use a database. You can take the approach and implement it using simple structs/classes/arrays.
I noticed this question lacks an extension answer, yes.. I'm gonna be that guy, so here it is. This could be made more generic by supporting other types of dictionaries, feel free to pitch in ;)
Inspiration from #eason's answer.
var newKV = [["remaining_balance": "420"],["remaining_balance": "490"],["remaining_balance": "500"]]
var array = [["id":"3", "sellingPrice":"520", "quantity":"15"], ["id":"5", "sellingPrice":"520", "quantity":"15"], ["id":"8", "sellingPrice":"520", "quantity":"15"]]
extension Array where Element == [String: String] {
enum UniquingKeysStrategy {
case old
case new
}
mutating func merge(with target: Array<Element>, uniquingKeysWith: UniquingKeysStrategy = .new) {
self = self.merged(with: target)
}
func merged(with target: Array<Element>, uniquingKeysWith strategy: UniquingKeysStrategy = .new) -> Array<Element> {
let base = self.count > target.count ? self : target
let data = self.count > target.count ? target : self
return data.enumerated().reduce(into: base, {
result, data in
result[data.offset]
.merge(data.element, uniquingKeysWith: {
old, new in
if strategy == .new { return new }
return old
})
})
}
}
let mergedArrays = newKV.merged(with: array, uniquingKeysWith: .old)
array.merge(with: newKV)
Happy Coding :)
Related
I have an array like this:
"vehicleStatus": [
{
"key": "TU_STATUS_PRIMARY_VOLT",
"value": "3.6"
},
{
"key": "TU_STATUS_PRIMARY_CHARGE_PERCENT",
"value": "100"
},
{
"key": "TU_STATUS_GSM_MODEM",
"value": "FUNCTIONING"
},
{
"key": "DOOR_IS_ALL_DOORS_LOCKED",
"value": "TRUE"
}
]
I want to retrieve the value of DOOR_IS_ALL_DOORS_LOCKED by filtering the array and without the "Repeat with each item" action.
I already filter arrays in other tools, JavaScript, Power Automate etc.
Is this possible in iOS Shortcuts?
I tried looping through all 97 items in this array and using IF condition to set a variable if the condition is met and then using that variable later, but it's long winded and takes too long for what I need.
1). For loop
First Solution of your problem, is already you have done.
Maybe you have done this by using for loop manually.
so second Option is
2). System Iterative
if let arrEle = vehicleStatus.first { $0.key == "DOOR_IS_ALL_DOORS_LOCKED"} {
print(arrEle.value)
}
or
if let arrEle = vehicleStatus.first { ($0 as? NsDict)?["key"] == "DOOR_IS_ALL_DOORS_LOCKED"} {
print((arrEle as? NsDict)?["value"] as? String)
}
or
if let arrEle = vehicleStatus.first { ($0 as? NsDict)?["key"] == "DOOR_IS_ALL_DOORS_LOCKED"},
let val = (arrEle as? NsDict)?["value"] as? String {
print(val)
}
you can change data management by
3). Dictionary
If 'vehicleStatus' has all data like you provide, then all data must be manage by dictionary.
let vehicleStatus = [
[
"key" : "TU_STATUS_PRIMARY_VOLT",
"value": "3.6"
],
[
"key" : "TU_STATUS_PRIMARY_CHARGE_PERCENT",
"value": "100"
],
[
"key" : "TU_STATUS_GSM_MODEM",
"value" : "FUNCTIONING"
],
[
"key" : "DOOR_IS_ALL_DOORS_LOCKED",
"value": "TRUE"
]
]
print(vehicleStatus)
let dict = Dictionary(uniqueKeysWithValues: vehicleStatus.map{ ($0["key"]!, $0["value"]! ) })
print(dict)
Here I need to get the index of particular array in which the key value pair item.defaultShipping == "true" then I need to the get the index of particular array and to pass in model class so that in order to get corresponding data so that it should be passed in another Api but when I tried below method it showing an error that Contexual type 'Any' cannot be used within dictionary literal in let parameters below line can anyone help me how to resolve this issue ?
here is my code
var i = 0
for item in customerShippingAddressModel {
if item.defaultShipping == "true" {
}
i += 1
}
let arr = customerShippingAddressModel[i]
let parameters : [String: Any] = ["address":
[ "region": "\(arr.region.region)",
"region_code": "\(arr.region.regionCode)",
"region_id": "\(arr.region.regionId)",
"country_id": "\(arr.countryId)",
"company": "\(arr.company)",
"telephone": "\(arr.telephone)",
"postcode": "\(arr.postCode)",
"city": "\(arr.city)",
"firstname": "\(arr.firstName)",
"lastname": "\(arr.lastName)",
"email": "\(arr.email)",
"prefix": "",
"sameAsBilling": 1,
"street": ["0": "\((arr.customerStreet[0])!)",
"1": "\((arr.customerStreet[1])!)"]]]
print(parameters)
Since Swift 3 you can use enumerated() which will allow you to have the index and the value as the following:
for (index, item) in customerShippingAddressModel.enumerated() {
if item.defaultShipping == "true" {
// you can get the item and index value here.
}
}
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)
I have two Dictionaries that look like:
var dict1 = [Int: [String: AnyObject]]
var dict2 = [Int: [String: AnyObject]]
for example:
dict1: [0: ["sender": "user1", "time": NSDate(), "mId": "as2f2ASf"], [1: ["sender": "user1", "time": NSDate(), "mId": "Sjf82FsJ"]
dict2: [0: ["sender": "user2", "time": NSDate(), "mId": "J2fAS92D"], [1: ["sender": "user2", "time": NSDate(), "mId": "Sjf82FsJ"]
I want to find out if the dictionaries have data with the same mId and if, I want to do some action.
I wrote this code for that and got these errors.
for (_, value) in dict1! {
for content in value {
if content.0 == "mId" {
var mID = content.1
for (_, 2ndValue) in dict2 {
for 2ndContent in 2ndValue {
if 2ndContent.0 == "mId" {
var 2ndMID = 2ndContent.1
if mID == 2ndMID {
//Do Some Action
}
}
}
}
}
}
}
Here are the errors:
https://www.dropbox.com/s/e28ple6640hkrzo/Bildschirmfoto%202015-08-28%20um%2021.21.54.png?dl=0
Firstly, as Eric says in his comment, you are getting errors because you can't start a variable name with a number.
Secondly what you are calling a 'dictionary' here is in fact an array of tuples - if you define your dict1 variable in the Swift REPL by running var dict1 = [Int,[String,AnyObject]()) you get:
dict1: [(Int, [String : AnyObject])] = 0 values
A dictionary with the equivalent structure would be defined thus:
var dict1 = [Int:[String:AnyObject]]() - this returns
dict2: [Int : [String : AnyObject]] = 0 key/value pairs
in the REPL.
Therefore the dict1 and dict2 declarations you show will not work. They need to be declared as follows to match the type you've specified:
var dict1 = [(0, ["sender": "user1", "time": NSDate(), "mId": "as2f2ASf"]), (1, ["sender": "user1", "time": NSDate(), "mId": "Sjf82FsJ"])]
var dict2 = [(0, ["sender": "user2", "time": NSDate(), "mId": "J2fAS92D"]), (1, ["sender": "user2", "time": NSDate(), "mId": "Sjf82FsJ"])]
If you want to use an actual dictionary, use :
var dict3 = [[0: ["sender": "user1", "time": NSDate(), "mId": "as2f2ASf"]], [1: ["sender": "user1", "time": NSDate(), "mId": "Sjf82FsJ"]]]
While I can see what you're trying to achieve in the code you've posted, I don't think the approach you're taking is the right one. Any time you have 4 levels of nested for loops you should consider whether there's a better way of solving the problem.
You are iterating over all the keys in the dictionary when you are only interested in the value of "mId". Just looking for the value of that key gets rid of 2 loops and a lot of pointless iterating over things you aren't interested in:
for (_,value1) in dict1 {
if let mld1 = value1["mId"] {
for(_,value2) in dict2 {
if let mld2 = value2["mId"] {
if mld1 == mld2 {
println("Found diff")
}
}
}
}
}
The if let is necessary to ensure you are making a valid comparison (i.e. to avoid a false positive if the value of 'mld' is nil in both dicts). No idea whether this is even possible in your data model but always worth being thorough. Note that this solution uses arrays of tuples, as in your examples - you'd need something slightly different if you use actual dictionaries.
Well im not sure i understood your problem, but this is my idea for that:
for (key, value) in dicOne {
for (keyTwo, valueTwo) in dicTwo {
for (keyItem,valueItem) in value {
for (keyItemTwo, valueItemTwo) in valueTwo {
if keyItem == keyItemTwo && valueItem == valueItemTwo{
println("do some action")
}
}
}
}
}
The first loop is for the first dictionary and the second, for the other dictionary. After this you'r in the second layer ["a": "A"] of both dictionaries. So the next step is to get this dictionary. For this are the other two loops.
Just a question: Did u tried tuple? Like this:
var dictionaryOne:[Int: (String, String)] = [1: ("a", "A")]
var dictionaryTwo:[Int: (String, String)] = [1: ("a", "A")]
for (key, value) in dictionaryOne {
for (keyTwo, valueTwo) in dictionaryTwo {
if value.0 == valueTwo.0 && value.1 == valueTwo.1 {
println("nice action")
}
}
}
I'm having trouble creating a specific structure in JSON with Swift. I use Swifty JSON for parsing but I can't figure out how to create one.
I have this array which is filled by Id's and quantity Ints of products in a shopping basket . I need to get the array into my JSON but I don't know how.
If you could help me with this I would be very glad :)
var productArray = Array<(id: Int,quantity: Int)>()
let jsonObject: [String: AnyObject] = [
"order": 1,
"client" : 1,
"plats": [
for product in productArray
{
"id": product.id
"quantity": product.quantity
}
]
]
You can't just start looping through stuff while defining your dictionary. Here's another approach.
First, create your array:
var productArray = Array<(id: Int,quantity: Int)>()
Add some products (for testing):
productArray += [(123, 1000)]
productArray += [(456, 50)]
Map this array into a new array of dictionaries:
let productDictArray = productArray.map { (product) -> [String : Int] in
[
"id": product.id,
"quantity": product.quantity
]
}
Use the new mapped array in your JSON object:
let jsonObject: [String: AnyObject] = [
"order": 1,
"client" : 1,
"plats": productDictArray
]
You are not supposed to do any kind of looping/condition making block of codes while creating Array's or Dictionary. For that you need to execute that piece of code outside, create a variable and use it.
Do try this way.
var productArray = Array<(id: Int,quantity: Int)>()
var prods = [[String:Int]]()
for product in productArray
{
var eachDict = [String:Int]()
eachDict["id"] = product.id
eachDict["quantity"] = product.quantity
prods.append(eachDict)
}
let jsonObject: [String: AnyObject] = [
"order": 1,
"client" : 1,
"plats": prods
]