how to get Int from elements of dictionary array. xcode - arrays

let products = ["гречка" : "12,3,68", "рис" : "7,1,74", "овсянка" : "12,6,65"]
let userInput = "р"
for pair in products { //
if pair.key.contains(userInput) {
let elements = pair.value.components(separatedBy: ",")
print(pair.key + " contains \(elements [0])")
I need elements [0] take unary operation: var = 150 + element [0]

This?
let products = ["гречка" : "12,3,68", "рис" : "7,1,74", "овсянка" : "12,6,65"]
let userInput = "р"
for pair in products { //
if pair.key.contains(userInput) {
let elements = pair.value.components(separatedBy: ",")
let number = 150 + Int(elements[0])!
print(pair.key + " contains \(number)")
}
}

Related

Get values from a textfield array

I would like to access the values of my textfield array but confused as the array I created is with tags.
So anyone knows how to get the value of the list (array) I created?
I want to create a function where I :
Get the value of the textfields on a list
Sort them by tags
get the value of each individual textfield
concatenate them in a string
1.Your collection Outlet will be something like this
#IBOutlet var textFields: [UITextFields]!
2. Sort it by tag
textFields.sort { $0.tag < $1.tag}
3. Use for loop to get value from array and concatenate it
var string = ""
for item in textFields {
string += item.text
}
Let's say you have following array,
var txtArray:[UITextField] = [UITextField]()
for i in 0...4 {
let txtField = UITextField(frame: .zero)
txtField.text = "\(i)"
txtField.tag = i
txtArray.append(txtField)
}
To get values you have to do following,
let sorted = txtArray.sorted { $0.tag < $1.tag }
let values = sorted.map { return $0.text! }
let test = values.joined(separator: " ")
print(test)
Output will be
0 1 2 3 4
Create an outlet connection and connect all your textfields to the same.
An outlet connection looks like
#IBOutlet strong var labels: [UILabel]!
Then to get all textfield contents and to append the same.
var resultString = ""
for item in enumerate(self.labels) {
resultString = resultString + item.text
}
Assume that you have array of UITextField
let textfield1 = UITextField()
textfield1.tag = 1
textfield1.text = "1"
let textfield2 = UITextField()
textfield2.tag = 2
textfield2.text = "2"
let textfield3 = UITextField()
textfield3.tag = 3
textfield3.text = "3"
let arrayOfTextFields :[UITextField] = [textfield2,textfield1,textfield3]
let result = self.getInputsValue(arrayOfTextFields, seperatedby: "-")
print(result)
Method you want :
func getInputsValue(_ inputs:[UITextField], seperatedby value: String) -> String {
return inputs.sorted {$0.tag < $1.tag}.map {$0.text}.compactMap({$0}).joined(separator: value)
}
Result:
1-2-3

Swift- How to add onto arraylist next index everytime save button is pressed

Hi my question is how can I store a string value which contails all textfield input into an array with new index every time I press save. I have created some code below however I think its overriding the first index.
#IBAction func Save (_ sender: UIButton){
let firstextfield = textfield1.text
let secondtextfield = textfield2.text
let allText = firsttextfield! + "," + secondtextfield!
var myArray = [String]()
var index : Int = 0
while (myArray.count) <= index {
myArray.insert(allText, at: index)
}
index +=
for element in myArray{
print(element)
}
}
input: firsttextfield = 9.22 and secondtextfield = 91.2
save button is then pressed.
output:
Optional ("9.22,91.2")
Optional ("")
if i were to then change the values of my textfields to firsttextfield = 0.2 and secondtextfield = 20.2
I get output :
Optional ("0.2,20.2")
Optional ("")
I dont want it to overide the array but to add onto it so expected output:
Optional ("9.22,91.2")
Optional ("0.2,20.2")
Any tips are welcome as I am new to coding.
//Just Declare outside of button action
var index = 0
var myArray = [String?]()
//Button action
#IBAction func btnShareTapped(_ sender: UIButton) {
let firstextfield = "textfield1.text"
let secondtextfield = "textfield2.text"
let allText = firstextfield + "," + secondtextfield
while (myArray.count) <= index {
myArray.append("")
}
myArray.insert(allText, at: index)
index = index + 1
for element in myArray{
print(element)
}
print(myArray)
}
Output
[Optional("textfield1.text,textfield2.text"), Optional("")]
[Optional("textfield1.text,textfield2.text"), Optional("textfield1.text,textfield2.text"), Optional("")]
//your last comment answer is
let a : String = myArray[0]!
let b = a.split(separator: ",")
label.text = b[0] as! String
label1.text = b[1] as! String
I think your emptying the array here:
var myArray = [String?]()
var index = 0
while (myArray.count) <= index {
myArray.append("")
}
declare and initialise it outside the function and then use this to insert values to array:
let allText = firsttextfield! + "," + secondtextfield!
anArray.append(allText)

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]

How to improve the speed of the code?

There is a speed problem with code below if the number of elements in arrayOfA is around 1000 and in arrayOfB around 100 000 (run time is about several minutes). How to improve the speed ?
let arrayOfA = [(String, String)]() //second string in tuple is about 30 characters
let arrayOfB = [String]() //string is about 200 characters
var arrayOfC = [(String, Int)]()
for i in 0..<arrayOfA.count
{
var amount = Int()
let name = arrayOfA[i].0 + " " + arrayOfA[i].1
for j in 0..<arrayOfB.count
{
if arrayOfB[j].range(of: arrayOfA[i].1) != nil
{
amount += 1
}
}
if amount > 0
{
arrayOfC += [(name, amount)]
}
}
Update
Meanwhile, I have made another code which is faster about 4 times. The idea is to avoid unnecessary repeating steps for function .range(of: string) . So, the first step is joining of reads with interval "_" Then, I can search to find all Range<String.Index> for stringA in the stringOfarrayOfB by using extension method searchForStringInString (which can find All Range<String.Index> of stringIn in stringOut).
let stringOfarrayOfB = arrayOfB.joined(separator: "_")
for i in 0..<arrayOfA.count
{
var amount = Int()
let arrayOfRanges = stringOfarrayOfB.searchForStringInString(stringOut: stringOfarrayOfB, stringIn: arrayOfA[i].1)
amount = arrayOfRanges.count
if amount > 0
{
let name = arrayOfA[i].0 + " " + arrayOfA[i].1
arrayOfC += [(name, amount)]
}
}
This is the code after it was changed with the suggested comments.
let arrayOfA = [(String, String)]() //second string in tuple is about 30 characters
let arrayOfB = [String]() //string is about 200 characters
var arrayOfC = [(String, Int)]()
for i in 0..<arrayOfA.count
{
var amount = Int()
for (index, stringB) in arrayOfB.enumerate().reverse()
{
if stringB.range(of: arrayOfA[i].1) != nil
{
amount += 1
arrayOfB.removeAtIndex(index)
}
}
if amount > 0
{
let name = arrayOfA[i].0 + " " + arrayOfA[i].1
arrayOfC += [(name, amount)]
}
}
Update
Same functionallity without reversing the array
let arrayOfA = [(String, String)]() //second string in tuple is about 30 characters
let arrayOfB = [String]() //string is about 200 characters
var arrayOfC = [(String, Int)]()
for i in 0..<arrayOfA.count
{
var amount = Int()
var indexesToDelete = []
for (index, stringB) in arrayOfB.enumerate()
{
if stringB.range(of: arrayOfA[i].1) != nil
{
amount += 1
indexesToDelete.append(index)
}
}
for (index, indexToDelete) in indexesToDelete {
arrayOfB.removeAtIndex(indexToDelete - index)
}
if amount > 0
{
let name = arrayOfA[i].0 + " " + arrayOfA[i].1
arrayOfC += [(name, amount)]
}
}
You can try this.
for i in 0..<arrayOfA.count {
var amount = Int()
let name = arrayOfA[i].0 + " " + arrayOfA[i].1
let tempArr = arrayOfB.filter { (string) -> Bool in
string.rangeOfString(arrayOfA[i].1) != nil
}
amount = tempArr.count
if amount > 0 {
arrayOfC += [(name, amount)]
}
}
arrayOfC += [(name, amount)]
}
In any case filter should be more effective than for loop.

How would I go about categorizing items within an Array in swift?

In swift, I want to categorize items in an existing array and place them accordingly in one new string.
Here is an example of what I want to do:
originalArray = ["hotdog","fries","hotdog","coke","coke","fries","hotdog"]
resultingString = "hotdog x 3, fries x 2, coke x 2"
How would I go about doing this?
Try this:
let originalArray = ["hotdog","fries","hotdog","coke","coke","fries","hotdog"]
var dict = [String: Int]()
let resultString = originalArray.reduce(dict) { _, element in
if dict[element] == nil {
dict[element] = 1
} else {
dict[element]! += 1
}
return dict
}
.map { "\($0) x \($1)" }
.joinWithSeparator(", ")
If you want to keep the original order of the array (ie: hotdog, fries, coke), the code is slightly more complicated:
let originalArray = ["hotdog","fries","hotdog","coke","coke","fries","hotdog"]
var dict = [String: (index: Int, count: Int)]()
let resultString = originalArray.enumerate()
.reduce(dict) { _ , e in
if let value = dict[e.element] {
dict[e.element] = (index: value.index, count: value.count + 1)
} else {
dict[e.element] = (index: e.index, count: 1)
}
return dict
}
.sort { return $0.1.index < $1.1.index }
.map { "\($0) x \($1.count)" }
.joinWithSeparator(", ")
print(resultString)
I think this will help you:
let originalArray = ["hotdog","fries","hotdog","coke","coke","fries","hotdog"]
var resultingString = ""
var counts:[String:Int] = [:]
for item in originalArray {
counts[item] = (counts[item] ?? 0) + 1
}
resultingString = counts.map { (key, value) -> String in
return "\(key) x \(value)"
}.joinWithSeparator(",")
print(resultingString)
Here is the output: coke x 2, hotdog x 3, fries x 2

Resources