Compare Two Different Structured Arrays in Swift3 - arrays

I am new to IOS as well as Swift Language, now I am working in Swift3.
DetailsArray:
[{
bookId = abcd;
bookName = "MyBook";
bookThumbImage = ".jpg"
},
{
bookId = efgh;
bookName = "MyBook1";
bookThumbImage = "bookefgh.jpg"
},
{
bookId = ijkl;
bookName = "MyBook2";
bookThumbImage = ".jpg"
}
]
When i print my Existing IdListArray Object is in the below given format,
IdListArray:
▿ Optional<"NSMutableArray">
▿ some : 2 elements
- 0 : abcd
- 1 : ijkl
Now i need to match these two Arrays (IdListArray & DetailsArray), to get the matched row record from my DetailsArray
Required Output:
[{
bookId = abcd;
bookName = "MyBook";
bookThumbImage = ".jpg"
},
{
bookId = ijkl;
bookName = "MyBook2";
bookThumbImage = ".jpg"
}]
Thanks,

Edited: As per your Requirement
You can use this code:
var arrMatchingId:NSMutableArray = NSMutableArray()
var arrNotMatchingId:NSMutableArray = NSMutableArray()
for data in arrList{
let id = (data as! NSDictionary).value(forKey: "bookId")
if arrID.contains(id!){
arrMatchingId.add(data) //Id Matched
}else{
arrNotMatchingId.add(data)// Id Not Matched
}
}
print(arrMatchingId) // This is the array with matched ID
print(arrNotMatchingId) //This is the array with Unmatched array

Related

Obtain values that match in two different arrays in Swift

In a service request, I obtain an array with this structure:
(
{
key = 1;
val = "Cookies";
},
{
key = 2;
val = Restaurante;
},
{
key = 22;
val = "Cereals";
},
{
key = 16;
val = "Shirts";
}
In a second request, I obtain another array of values that are related to the array of the first request:
▿ Optional<NSArray>
▿ some : 5 elements
- 0 : 1
- 1 : 2
- 2 : 5
- 3 : 19
- 4 : 20
What I need is to show in a tableView the text of the first array whose keys I obtain in the second array, how could I do that?
It looks like you obtain that types of arrays
struct ArrayObject {
let key: Int
let value: String
}
let objectArray: [ArrayObject] = []
let keysArray: [Int] = []
Then you need to use filter to determine what keys are contains in second array:
// if you need objects
let filteredObjectsResult = objectArray.filter { keysArray.contains($0.key) }
// if you need values only
let filteredValuesResult = filteredObjectsResult.map { $0.value }

How to Sort an Array of NSDictionary using DateTime key (Swift 4)?

I have an NSArray of NSDictionary
let Array = (
{ name = "Auni";
age = "24";
transactionTime = "01-02-2011 12:32:39" },
{ name = "Atiqah";
age = "23";
transactionTime = "02-02-2013 10:32:41" },
{ name = "Aida";
age = "22";
transactionTime = "04-02-2020 18:32:21"})
How do I sort this array by most recent transactionTime? Using Swift4.
Thank you.
Edit: It's easier to have back-end people do it for you.
You do not need to convert into Date object, dateStrings direct comparison will also work.
array.sort { (dict1, dict2) -> Bool in
/// Considering "transactionTime" key always exists.
let transactionTime1 = dict1["transactionTime"]!
let transactionTime2 = dict2["transactionTime"]!
/// Sort in descending order
return transactionTime1 > transactionTime2
}
In case you need some calculation on date objects then You can also convert the string into date objects at run time like below example:
let df = DateFormatter()
df.dateFormat = "dd-MM-yyyy HH:mm:ss"
array.sort { (dict1, dict2) -> Bool in
/// Considering "transactionTime" key always exists.
let transactionTime1 = dict1["transactionTime"]!
let transactionTime2 = dict2["transactionTime"]!
let date1 = df.date(from: transactionTime1)!
let date2 = df.date(from: transactionTime2)!
/// Sort in descending order
return date1 > date2
}
print(array)
Output
[["transactionTime": "04-02-2020 18:32:21", "name": "Aida", "age": "22"], ["transactionTime": "02-02-2013 10:32:41", "name": "Atiqah", "age": "23"], ["transactionTime": "01-02-2011 12:32:39", "name": "Auni", "age": "24"]]

Counting unique ids within nested array using Swift

I have the following nested array and I'm trying to count how many items with unique ids there are. In the array below the count should be 2.
Array is of type List<SolData> it comes from Realm
class SolData: Object {
#objc dynamic var uid = "";
#objc dynamic var id = "";
}
extension SolData: ListDiffable {
func diffIdentifier() -> NSObjectProtocol {
return uid as NSObjectProtocol
}
func isEqual(toDiffableObject object: ListDiffable?) -> Bool {
if let object = object as? SolData {
return uid == object.uid
}
return false
}
}
Print of the array.
(
[0] SolData {
uid = sdasd;
id = jmX3;
},
[1] SolData {
uid = gfd;
id = jmX3;
},
[2] SolData {
uid = hgfd;
id = jmX3;
},
[3] SolData {
uid = terw;
id = jmX3;
},
[4] SolData {
uid = fgg;
id = GFdda;
}
)
I tried to use map in the following way
var count = 0;
var prevId = "";
let uniqueSols = diff.sol.map{ (s) -> Int in
if s.id != prevId {
count = count + 1;
prevId = s.id;
}
return count;
}
print(uniqueSols);
But I get the following error.
SWIFT RUNTIME BUG: unable to demangle type of field '_transform'. mangled type name is 'q_7ElementSTQzc'
2018-10-27 14:26:08.793528+0300 App[23634:611928] SWIFT RUNTIME BUG: unable to demangle type of field '_transform'. mangled type name is 'q_7ElementSTQzc', _transform: ())
To reproduce your code, I am going to mock the SolData class and add an initializer to make instantiation easier:
class SolData {
var uid: String = ""
var id: String = ""
init(uid: String, id: String) {
self.uid = uid
self.id = id
}
}
Let's create a few of instances:
let zero = SolData(uid: "sdasd", id: "jmX3")
let one = SolData(uid: "gfd", id: "jmX3")
let two = SolData(uid: "hgfd", id: "jmX3")
let three = SolData(uid: "terw", id: "jmX3")
let four = SolData(uid: "fgg", id: "GFdda")
And group them in an array:
let array = [zero, one, two, three, four]
To get only instances that have unique ids, let's use reduce(into:) :
let uniqueIds = array.reduce(into: Set<String>(), { $0.insert($1.id)})
The count property of uniqueIds is the number of unique ids in array:
let uniqueIdsCount = uniqueIds.count //2
If you want an array of instances with unique ids, use the following:
let instancesWithUniqueIds = array.reduce(into: [SolData]()) { accumulator, element in
if accumulator.allSatisfy({ $0.id != element.id}) {
accumulator.append(element)
}
}
accumulator.allSatisfy({ $0.id != element.id}) maybe replaced by accumulator.contains(element) and making SolData conform to Hashable.

How to group the same element in array and sum it in Swift?

How to filter duplicate category element into different array and count their amount?
This is the format, record is from the core data.
var record = [Record]()
[<Record:...; data: {accountbook = "MyBook";
amount = "10.50";
category = "A";
id = 1;
},<Record:...; data: {accountbook = "MyBook";
amount = "5.50";
category = "B";
id = 2;
},<Record:...; data: {accountbook = "MyBook";
amount = "4.50";
category = "B";
id = 3;
}]
What I want
var category = ["A", "B"] //success
var total = [10.50, 10.00]
This is what I do for finding the category, and it works but how to group the same category and sum the total?
var category =[String]()
for categoryObject in record{
if let categoryItem = categoryObject.category{
category.append(categoryItem)
}
}
//I tried this code to group the same category but fail.
let result = Set(record).map{ category in return record.filter{$0 == category} }
Another way is this. but how if I have A-Z category? it will have very long code..Is there any way can detect the same value and split it to different array so that I can sum it by category.
categoryFilter = record.filter { $0.category!.contains("A") }
First group your record object by category like this
extension Sequence {
func group<GroupingType: Hashable>(by key: (Iterator.Element) -> GroupingType) -> [[Iterator.Element]] {
var groups: [GroupingType: [Iterator.Element]] = [:]
var groupsOrder: [GroupingType] = []
forEach { element in
let key = key(element)
if case nil = groups[key]?.append(element) {
groups[key] = [element]
groupsOrder.append(key)
}
}
return groupsOrder.map { groups[$0]! }
}
}
Then you will get your distinct arrays based on category like this
var records : [Record] = []// your objects
let distinctRecords = records.group(by: {$0. category})
Now you can use reduce to calculate sum of values of that category
for items in distinctRecords{
let sum = items.reduce(0.0){$0.0 + $1. amount ?? 0.0}// assuming you have float values in your amount
print(items)// do whatever you want to do with your distinct array
print(" \(sum)")
}
#Wan Jern I have written a piece of code, you can try this one. Hopefully, it will work.
var category = [String]()
var totalArr = [CGFloat]()
for categoryObject in record{
if let categoryItem = categoryObject.category{
if !category.contains(categoryItem) {
category.append(categoryItem)
totalArr.append(categoryObject.amount)
} else {
let index = category.index(of: categoryItem)
let itemAtIndex = category[index]
let itemAtIndex = itemAtIndex + categoryObject.amount
totalArr.insert(itemAtIndex, at: index)
}
}
}
Do you have your record struct in a class model?
like my data model selected from sqlite:
//Data model
import Foundation
import UIKit
class scoreModel: NSObject {
var lessonName:String = String()
var lessonCode:String = String()
var creditPoint:Double = Double()
var totalStudentNumber:Int = Int()
var teacherName:String = String()
var semesterName:String = String()
var scoreValue:String = String()
var studentCount:Int = Int()
}
If the answer is yes, we can use pointer in array and repeat while loop to do this manually.
Like my code:
let mysql = ""
let dataArray = SQLiteManager.shareInstance.queryDB(sql:mysql)
var i = 0
while i<dataArray.count-1
{
var scoreArray = [Dictionary<String, Int>]()
var range = 0
var test = 0
test = i
//print("pointer i is'\(test)'")
while ((dataArray[test]as! scoreModel).lessonCode == (dataArray[test+range]as! scoreModel).lessonCode && (test+range)<dataArray.count-1)
{
let key = (dataArray[test+range]as! scoreModel).scoreValue
let value = (dataArray[test+range]as! scoreModel).studentCount
var dict: [String: Int] = [String: Int]()
dict[key] = value
scoreArray.append(dict)
//print("working pointer is'\(test+range)'")
range = range+1
}
//transfer array
let model:resultModel = resultModel()
model.lessonName = (dataArray[test]as! scoreModel).lessonName
model.lessonCode = (dataArray[test]as! scoreModel).lessonCode
model.creditPoint = (dataArray[test]as! scoreModel).creditPoint
model.semesterName = (dataArray[test]as! scoreModel).semesterName
model.teacherName = (dataArray[test]as! scoreModel).teacherName
model.totalStudentNumber = (dataArray[test]as! scoreModel).totalStudentNumber
model.scoreArray = scoreArray
resultArray.add(model)
i = i+range
//print("range is'\(range)'")
}
Make the Records as Hashable with "category" as the unique in stubs function
struct Record: Hashable {
var accountbook = ""
var category = ""
var amount = 0.0
// added from stubs of Hashable
var hashValue: Int { return category.hashValue }
static func ==(lhs: Record, rhs: Record) -> Bool {
return lhs.category == rhs.category
}
}
Then filter the unique categories
let categories = Set(record).map { $0.category }
print(categories) // ["B", "A"]
And make a sum of each category
let totals = categories.map { c in
record.filter { $0.category == c }.map{ $0.amount }.reduce(0, +)
}
print(totals) // get the sums as [10.0, 10.5]

Filtering dictionary inside an array in Swift

I have An Array With Dictionary example :
[{
"CATEGORYNAME" = "name0";
"CATEGORYSUBID" = 2;
"ID" = 1;
}, {
"CATEGORYNAME" = "name1";
"CATEGORYSUBID" = 2;
"ID" = 2;
}, {
"CATEGORYNAME" = "name2";
"CATEGORYSUBID" = 0;
"ID" = 3;
}]
I Used to Filter it in Objective C Like this
JSON_data = [[[Global SharedData]Categorys] filteredArrayUsingPredicate:
[NSPredicate predicateWithFormat:#"(CATEGORYSUBID == %#)", Filter]];
i tried To Use Array Filter but not Succeed
var JSON_data = Global.SharedData().Categorys
JSON_data = JSON_data.filter( ?????
JSON_data is has all data i have print it with Printin
Filtering a dictionary would be simple like below. We filter ages that are below 30.
var visitors = [["age" : 22], ["age" : 41], ["age" : 23], ["age" : 30]]
var filteredVisitors = visitors.filter({
$0["age"] < 30 //access the value to filter
})
println(filteredVisitors)
//[["age" : 22], ["age" : 23]]
More info here: Filtering a Swift Array of Dictionaries or Object property
This looks like just a simple question in how to translate. Your best option is to go through the various Sessions from WWDC, but a literal translation is:
let categories = Global.SharedData().Categorys()
JSON_data = categories.filter({
if let subid = $0["CATEGORYSUBID"] {
return subid == filter
} else {
return false
}
})
If that doesn't work you'll need to post a lot more information about how Global, SharedData, Categorys and JSON_data.

Resources