Swift 2 String Array remove Spesific Index Error - arrays

I have String Array;
var students = [String]()
and my students array output :
students[0]:102----3----
students[1]:102-2018.07.24-4--6---
students[2]:103--5--4--
students[3]:34-2018.07.24---3-4--6--
students[4]:34--6---5----4--
I want to remove students[0] so students[1] same id with students[0] and students[0] dont have date.
I want to remove students[4] so students[3] same id with students[4] and students[4] dont have date.
In Swift 2 how can i do it ?
Must be output
students[0]:102-2018.07.24-4--6---
students[1]:103--5--4--
students[2]:34-2018.07.24---3-4--6--
My test codes;
var count = 0
for mystudents in self.students {
let explode1 = "\(mystudents)".componentsSeparatedByString("-")
let explode2 = "\(mystudents)".componentsSeparatedByString("-")
if (explode1[0] == explode2[0]) { // HERE if equal same ids
if (explode1[1] == "" || explode2[1] == ""]){
self.students.removeAtIndex(count++) // HERE gives fatal error: Index out of range
}
}
}
And
i didnt fix tihs about 5 days , who will fix this i will give 500 reps after 2 days with bounty

I am suggesting the below solution on the understanding that you want to remove an object that has only id and it matches with other object that has same id and date. If my understanding is wrong, please let me know,
let students = ["102----3----",
"103--5--4--",
"102-2018.07.24-4--6---",
"34-2018.07.24---3-4--6--",
"34--6---5----4--"]
let filtered = students.filter { (student) -> Bool in
let id = student.characters.split{$0 == "-"}.map({ String($0) })
let exists = students.filter({ (other) -> Bool in
if student == other {
return false
}
let otherId = other.characters.split{$0 == "-"}.map({String($0) }).first!
return id.first! == otherId
}).first
if exists != nil, id.count > 1 {
return id[1].characters.filter({ $0 == "."}).count == 2
}
return true
}
print(filtered)
Output:
["103--5--4--", "102-2018.07.24-4--6---", "34-2018.07.24---3-4--6--"]

Related

Swift: I want to sort the series I have by the number of 'a' in the names' surnames. The name and surname in the series are in the same index

app image
I can check the number of "a" in this array I have, but I could not find how I should sort it.
write a String extension function that will help you count the number of occurrences of a character in a string.
rite a function that will receive an array of strings and a character. This function will be responsible for sorting members in the array with respect to following rules:
i. By using the extension function you wrote, find the most occurences of the character for each string in the array and sort in descending order.
ii. If two or more strings contain the same amount for the character, sort these according to their length.
iii. If two or more strings contain the same amount for the character and have the same length, sort these in alphabetical order.
Example:
let array = ["xxx baba", "yyy bababa"," zzz bbaba","ggg sjsj"]
return = ["yyy bababa", " zzz bbaba", "xxx baba", "ggg sjsj"]
When the Sort button is tapped, please call this function for the last names of the members, for the character “a” and update the UI with respect to the sorted list.
for your first question
func FindingNoofCh( array : [String]) {
var SearchHash : Dictionary<Character , Int> = [:]
for string in array {
for (index , ch) in string.enumerated() {
if ch.isWhitespace {
continue
}
let alreadyExit : Bool = SearchHash[ch] != nil
if alreadyExit {
SearchHash[ch]! += 1
print("no of times \(ch) is \(SearchHash[ch]!) times")
}else {
SearchHash[ch] = 1
print("no of times \(ch) is \(SearchHash[ch]!) times")
}
}
SearchHash = [:]
}
}
for second function:
func SortingMembers(array : [String] , ch : Character) -> [String] {
var SearchHash : Dictionary<Character , Int> = [:]
var history : [Dictionary<Character , Int>] = [[:]]
let array = array
var returningarray : [Dictionary<String , Int>] = [[:]]
var x : Int = 0
for string in array {
for (_ , ch) in string.enumerated() {
if ch.isWhitespace {
continue
}
let alreadyExit : Bool = SearchHash[ch] != nil
if alreadyExit {
SearchHash[ch]! += 1
}else {
SearchHash[ch] = 1
}
}
history.append(SearchHash)
SearchHash = [:]
}
history.removeFirst()
print(history)
returningarray.removeFirst()
for (index , eachhistory) in history.enumerated() {
if let amount = eachhistory[ch] {
print(amount)
if amount > x {
x = amount
returningarray.insert([array[index] : amount], at: 0)
continue
}
if amount == x && array[index-1].count != array[index].count {
if array[index-1].count < array[index].count{
returningarray.insert([array[index] : amount], at: index-1)
}else {
returningarray.append([array[index] : amount])
}
}else if amount == x && array[index-1].count == array[index].count {
if array[index] > array[index - 1] {
returningarray.insert([array[index] : 0], at: index-1)
}else {
returningarray.append([array[index] : 0])
}
}
}
returningarray.insert([array[index] : 0], at: returningarray.endIndex)
}
var finalarray = [String]()
for array in returningarray {
for (data,_) in array {
finalarray.append(data)
}
}
print(finalarray)
return finalarray
}
you can optimize yourself as its by brute force.
give it a vote and let me know :)

Swift display previous entered item in array

I am trying to display the pervious entered exercise attributes in the current workout. If I go to the pervious workout everything shows up but when I go to my current workout the previous exercise attributes don't show and the date label only shows today's date and not the previous workout date. Here are the two functions for the issue. Let me know if i need to post more.
func lastWorkout() -> Workout? {
if let client = currentClient(), let currentWorkout = currentWorkout(), let workouts = client.workouts as? Set<Workout> {
// get all this client's workouts in cronological order
let sortedWorkouts = workouts.sorted { (one, two) -> Bool in
let scheduledTimeOfOne = one.appointment?.scheduled ?? Date(timeIntervalSince1970: 0)
let scheduledTimeOfTwo = two.appointment?.scheduled ?? Date(timeIntervalSince1970: 0)
return scheduledTimeOfOne > scheduledTimeOfTwo
}
// get the index of this workout
let indexOfTodaysWorkout = sortedWorkouts.index(of: currentWorkout) ?? 0
// go back one workout to find the last workout completed
let lastWorkout: Workout? = (indexOfTodaysWorkout - 1) < 0 ? nil : sortedWorkouts[indexOfTodaysWorkout - 1]
// and return
return lastWorkout
}
return nil
}
/// Last Exercise Info to load previous exercise data
func lastExercise() -> Exercise? {
guard let selectedExercise = currentExerciseInfo() else{
return nil
}
if let exercises = lastWorkout()?.exercises as? Set<Exercise>, let pastExercise = exercises.first(where: { $0.exerciseInfo == selectedExercise }) {
return pastExercise
}
return nil
}
So the array count was off in last workout function. Here is what the working function looks like. I am still not displaying the proper date. it just gives today's date.
func lastWorkout() -> Workout? {
if let client = currentClient(), let currentWorkout = currentWorkout(), let workouts = client.workouts as? Set<Workout> {
// get all this client's workouts in cronological order
let sortedWorkouts = workouts.sorted { (one, two) -> Bool in
let scheduledTimeOfOne = one.appointment?.scheduled ?? Date(timeIntervalSince1970: 0)
let scheduledTimeOfTwo = two.appointment?.scheduled ?? Date(timeIntervalSince1970: 0)
return scheduledTimeOfOne > scheduledTimeOfTwo
}
// get the index of this workout
let indexOfTodaysWorkout = sortedWorkouts.index(of: currentWorkout) ?? 0
// go back one workout to find the last workout completed
let lastWorkout: Workout? = sortedWorkouts.count < 2 ? nil : sortedWorkouts[indexOfTodaysWorkout + 1]
// and return
return lastWorkout
}
return nil
}

how do i make sure users can't enter in duplicates?

Spent all day on this one. I have an array of expenses that populates my tableview. Users can select a row from the tableview to edit the expense, which includes the name, the amount, the due date, etc.
I don't want users to be able to enter in a duplicate name. What I mean is, I want to check their input against the array to make sure the name doesn't already exist. This sounds simple to me, but for some reason I can't get it to work.
This is what I've tried:
CODE #1:
var duplicateCount = 0
for item in Expense.expensesArray.filter({ $0.ownerName == currentUserName }).filter({ $0.category == expense?.category }) {
if item.expenseName != expense?.expenseName {
print("no duplicates found in \(item.expenseName). moving on")
} else if item.expenseName == expense?.expenseName {
duplicateCount += 1
print("duplicate found in \(item.expenseName)")
}
}
CODE #2: (which is pretty similar to #1)
var duplicatesAmount: Int = 0
for expense in Expense.expensesArray.filter({ return $0.ownerName == currentUserName }).filter({ $0.category == expense?.category }) {
if expense.expenseName.lowercased() == expenseNameTextField.text?.lowercased() {
duplicatesAmount += 1
print("POTENTIAL DUPLICATE #\(duplicatesAmount): ",expense.expenseName)
}
}
// if there is more than one expense in the array with the same name, return true
if duplicatesAmount > 1 {
return true
} else {
return false
}
EDIT: The code runs whether there's a duplicate or not. It never sees the duplicate, even if I purposely put one in.
UPDATE: This worked.
if expense?.expenseName == expenseNameTextField.text {
updateExpenseInfo()
} else {
// iterate over the array and see if new name is found anywhere
let dupArray = Expense.expensesArray.filter({ $0.ownerName == currentUserName && $0.category == expense?.category && $0.expenseName == expenseNameTextField.text })
if dupArray.isEmpty {
updateExpenseInfo()
} else {
duplicateNameAlert()
}
}
You can do it like this:
struct Object {
let name: String
let amount: Int
init(name: String = "", amount: Int = 0) {
self.name = name
self.amount = amount
}
}
let a = Object(name: "Foo", amount: 10)
let b = Object(name: "Bar", amount: 20)
let array = [a, b]
func contains(value: String) -> Bool {
return array.filter({ $0.name == value }).isEmpty
}
print(contains(value: "Foo")) // true
print(contains(value: "Test")) // false
So you basically just add the contains function and return array.filter({ $0.name == value }).isEmpty. If it returns true then save otherwise don´t save. The value you pass it the entered value.

Find element in an array of object

I created an array of objects:
var fullMonthlyList = [SimulationMonthly]()
The class here:
class SimulationMonthly {
var monthlyMonthDuration: NSNumber = 0
var monthlyYearDuration: NSNumber = 0
var monthlyFullAmount: NSNumber = 0
var monthlyAmount: Int = 0
init(monthlyMonthDuration: NSNumber, monthlyYearDuration: NSNumber, monthlyFullAmount: NSNumber, monthlyAmount: Int){
self.monthlyMonthDuration = monthlyMonthDuration
self.monthlyYearDuration = monthlyYearDuration
self.monthlyFullAmount = monthlyFullAmount
self.monthlyAmount = monthlyAmount
}
}
I just did append to populate it, now I want to find for example if they're an existing value, for example monthlyAmount equals to "194" by search in the array, how can I do ? I have tried filter and contains but I get errors.
What I've tried:
if self.fullMonthlyList.filter({ $0.monthlyAmount == self.monthlyAmount.intValue }) { ... }
Error:
Cannot invoke 'filter' with an argument list of type '((SimulationMonthly) throws -> Bool)'
You can do:
if let sim = fullMonthlyList.first(where: { $0.monthlyAmount == 194 }) {
// Do something with sim or print that the object exists...
}
This will give you the first element in your array where monthlyAmount equals 194.
If you want all elements with that condition, you can use filter:
let result = fullMonthlyList.filter { $0.monthlyAmount == 194 }
If you don't need the object at all but you just want to know if one exists, then contains would be enough:
let result = fullMonthlyList.contains(where: { $0.monthlyAmount == 194 })
Here's a simple playground example of filtering objects based on matching a property. You should be able to expand it to your situation.
class Item {
var value: Int
init(_ val: Int) {
value = val
}
}
var items = [Item]()
for setting in 0..<5 {
items.append(Item(setting))
}
func select(_ with: Int) -> [Item] {
return items.filter { $0.value == with }
}
let found = select(3)

Search and use of Strings in 2D Arrays

I got a 2D array where I want to fetch data from the 2nd dimension based on the 1st, but I dont understand how to set it up in Swift 2 since the old for-loop function is deprecated.
Based on the name (Burt) I want to present the phone-No and Group.
myArray: [[String]] = [["Adam", "123456", "Group1"], ["Burt", "251436", "Group2"], ["Cesar", "918273", "Group3"], ["David", "552277", "Group4"]
For i in 0..myArray.count {
If myArray[i][0] == "Burt" {
phoneNoLabel.text = myArray[i][1]
  GroupNoLabel.text = myArray[i][2]
}
}
This is how I solved it with the help of Tarun Seera.
let myArray = [["Adam", "123456", "Group1"], ["Burt", "251436", "Group2"], ["Cesar", "918273", "Group3"], ["David", "552277", "Group4"]]
var user: String = "Burt"
var phoneNo: String = ""
var groupNo: String = ""
for i in myArray {
if i[0] == user {
phoneNo = i[1]
groupNo = i[2]
}
}
You can also make entities (NSObject)array and use predicate to achieve the same thing and still if you want this form 2d array you can use below code
let myArray = [["Adam", "123456", "Group1"], ["Burt", "251436", "Group2"], ["Cesar", "918273", "Group3"], ["David", "552277", "Group4"]]
for i in myArray {
if i[0] == "Burt" {
print("Hurrey I am in.. my name is: \(i[0]) my Id is:\(i[1]) and my gourp is:\(i[2])")
}
}
for i in 0..<myArray.count {
if myArray[i][0] == "Burt" {
phoneNoLabel.text = myArray[i][1]
GroupNoLabel.text = myArray[i][2]
}
}
Use
..<
instead of just
..
Your problem is, that i is going from 0 to myArray.count - which is 4 .. that means your i is going 0,1,2,3,4 = you have 5 times i. Your array only has 4 "items".
for i in 1...myArray.count{
if myArray[i-1][0] == "Burt" {
phoneNoLabel.text = myArray[i-1][1]
GroupNoLabel.text = myArray[i-1][2]
}
}
or
for i in 0...myArray.count-1{
if myArray[i][0] == "Burt" {
phoneNoLabel.text = myArray[i][1]
GroupNoLabel.text = myArray[i][2]
}
}
should solve your problem.
As an alternative to explicit looping, you could use a functional programming approach
let searchForUser = "Burt"
let userInfo = Array(myArray
.flatMap{ $0.first == searchForUser ? $0.suffixFrom(1) : nil }
.flatten())
print(userInfo) // ["251436", "Group2"]
For you specific example, the user info you're after is readily obtainable from the userInfo array
phoneNoLabel.text = userInfo[0] // 251436
groupNoLabel.text = userInfo[1] // Group2
Note here that I've renamed GroupNoLabel variable (UILabel?) from the example in your question to groupNoLabel, as variables in Swift should, by convention, use camelCase names (and not CamelCase, as is used e.g. for types).

Resources