This question already has an answer here:
Swift: sorting of array is not done correctly
(1 answer)
Closed 7 years ago.
I have an Array containing values like 7-4.json, 87-1.json and 102-4.json and want to sort it (ascending). I used the following code:
var fileNames = ["7-4.json", "87-1.json", "102-4.json"]
fileNames = fileNames.sort{ $0 < $1 }
print(fileNames)
which results in:
["102-4.json", "7-4.json", "87-1.json"]
So it didn't worked as I aspected. How can I sort it like 7-4, 87-1, 102-4?
Here you go:
var fileNames = ["7-4.json", "87-1.json", "102-4.json"]
func sortWithCustomFormat(first: String, second: String) -> Bool{
func extract(value: String) -> (Int, Int){
return (Int(value.componentsSeparatedByString("-").first!)!, Int(value.componentsSeparatedByString("-").last!.componentsSeparatedByString(".").first!)!)
}
let firstNumber = extract(first)
let secondNumber = extract(second)
if firstNumber.0 != secondNumber.0 { return firstNumber.0 < secondNumber.0 }
return firstNumber.1 < secondNumber.1
}
fileNames.sort(sortWithCustomFormat)
The function sortWithCustomFormat has a function extract that takes the inputted string and extracts the first and second numbers from it. Then, you compare the first numbers. If they are equal, then you compare the second numbers.
var fileNames = ["87-1.json", "7-4.json", "87-3.json", "102-4.json"]
fileNames = fileNames.sort({ (s1, s2) -> Bool in
let f1 = s1.stringByReplacingOccurrencesOfString(".json", withString: "")
let f2 = s2.stringByReplacingOccurrencesOfString(".json", withString: "")
let arr1 = f1.componentsSeparatedByString("-")
let arr2 = f2.componentsSeparatedByString("-")
var int1 = Int(arr1[0])
var int2 = Int(arr2[0])
if int1 < int2 {
return true
}
else if int1 > int2 {
return false
}
else {
int1 = Int(arr1[1])
int2 = Int(arr2[1])
if int1 < int2 {
return true
}
else if int1 > int2 {
return false
}
else {
return true
}
}
});
print(fileNames)
Try this...
var fileNames = ["87-1.json", "7-4.json", "102-4.json"]
// Modded OP's order to actually test sort
var sorted = fileNames.sort{ $0 < $1 }
print(sorted) // ["102-4.json", "7-4.json", "87-1.json"]
// Not sorted as OP "required", as they are string sorted, not number sorted
// Very simplistic solution
sorted = fileNames.sort { ($0 as NSString).integerValue < ($1 as NSString).integerValue}
print(sorted) // As OP requires, but...
// It won't sort on his count field - add a failing case...
fileNames = ["7-4.json", "87-1.json", "102-4.json", "102-1.json"]
sorted = fileNames.sort { ($0 as NSString).integerValue < ($1 as NSString).integerValue}
print(sorted) // ["7-4.json", "87-1.json", "102-4.json", "102-1.son"]
// WRONG!
// Define a simple function that parses his strings into tuples.
// This assumes that the Strings are valid, and fails safe if not.
// If you want more validation, add it yourself!
func myParse(s: String) -> (Int, Int) {
let c = s.componentsSeparatedByCharactersInSet(NSCharacterSet(charactersInString: "-."))
switch c.count {
case 0:
print("Careful Will Robinson!")
return (0, 0)
case 1:
print("Careful Will Robinson!")
return ((c[0] as NSString).integerValue, 0)
default:
return ((c[0] as NSString).integerValue, (c[1] as NSString).integerValue)
}
}
let test = fileNames.map { myParse($0) }
print("\(test)") // Test execution of function
sorted = fileNames.sort { (s1: String, s2: String) -> Bool in
let t1 = myParse(s1)
let t2 = myParse(s2)
if t1.0 == t2.0 {
return t1.1 < t2.1
} else {
return t1.0 < t2.0
}
}
print(sorted) // As required ["7-4.json", "87-1.json", "102-1.json", "102-4.json"]
Related
This is my code
create a program using closure that will return the equivalent binary value of the given array hexadecimal value.
let hexBin = [0:"0000", 1:"0001", 2:"0010", 3:"0011", 4:"0100", 5:"0101", 6:"0110", 7:"0111",
8:"1000", 9:"1001", A:"1010", B:"1011", C:"1100", D:"1101", E:"1110", F:"1111"]
var myNumArr = [123, ABC, 4DE, F05]
let myCovertedValue = myNumArr.map{
num -> String in
var num = num
var output = ""
repeat {
output = hexBin[num % 10]! + output
num /= 10
} while(num > 0)
return output
}
print(myCovertedValue)
Output should be like this
["000100100011", "101010111100", "010011011110", "111100000101"]
The number 123 is working but I don't know how will it works in letter only and number in mix.
func hexToBinary(array : [String]) -> [Any]{
return array.map{ String(Int($0, radix: 16)!, radix: 2).pad(with: "0", toLength: 12)}
}
extension String {
func pad(with character: String, toLength length: Int) -> String {
let padCount = length - self.count
guard padCount > 0 else { return self }
return String(repeating: character, count: padCount) + self
}
}
print(hexToBinary(array: myNumArr)) //["000100100011", "101010111100", "010011011110", "111100000101"]
I am trying to prints counts of a duplicate from an input string through the use of hash map. I am not sure why solution is not working. I come from a python background
//Write an efficient program to print all the duplicates and their counts in the input string
func letters(inputs: String)->[Character:Int] {
var result = [Character:Int]()
for input in inputs {
if let value = result[input] {
return [input : value]
}
else {
result[input] = (result[input] ?? 0)+1
}
}
return [:]
}
letters(inputs:"geeksforgeeks")
["e": 1]
Try this:
func letters(inputs: String) -> [Character:Int] {
var result = [Character:Int]()
for input in inputs{
if let value = result[input] {
result[input] = value + 1
}
else{
result[input] = 1
}
}
return result
}
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 :)
Here is my code, inside of my for loop, there is a while loop changes
the variable i's value. I printed out the value of i before while loop
and and after loop, the new "before index value" is expected to start
at "after index value +1". However, the "new before index value" just
increase as normal, which increase one each time. Appreciate your time.
class Solution
{
func summaryRange(nums: [Int]) -> [String]
{
var result = [String]()
if nums.count == 1
{
result.append(String(nums[0])+"")
return result
}
for var i in (0...nums.count-1)
{
let a = nums[i]
print("before: \(i)")
while i+1<nums.count && (nums[i+1] - nums[i] == 1)
{
i += 1
}
if a != nums[i]
{
result.append(String(a) + "->" + String(nums[i]))
}
else
{
result.append(String(a)+"")
}
print("after: \(i)")
}
return result
}
}
var test = Solution()
var input = [0,1,2,4,5,7]
var result = test.summaryRange(input)
print(result)
This code tries to get result like ["0->2","4->5","7"]
This is my own solution. I figure out the problem. Basically, I switch
the "for loop" to a "while loop". Then, it works.
class Solution
{
func summaryRanges(nums: [Int]) -> [String]
{
var result = [String]()
var i = 0
while(i<nums.count)
{
let a = nums[i]
while i+1<nums.count && (nums[i+1] - nums[i] == 1)
{
i += 1
}
if a != nums[i]
{
result.append(String(a) + "->" + String(nums[i]))
}
else
{
result.append(String(a)+"")
}
i += 1
}
return result
}
}
In swift, for in loop is a wrapper around the Sequence Type. In this particular case, 0...numCount-1 is a Sequence of Ints. When you call for in this is what happens internally.
let a = 0..<5
var generator = a.generate()
while var i = generator.next() {
print(i + 1)
i+= 1
}
So even if you increment the value of i inside the loop, it wont affect the loop itself. This is because loop is controller only by calling genertator.next().
This helps understand the basics.
This was an interesting one. I think this does the trick (with some code cleanup as well :-]
class Solution
{
func summaryRange(nums: [Int]) -> [String] {
var result = [String]()
var currentRange = [Int]()
for num in nums {
if currentRange.isEmpty { //if range is empty, start a new range
currentRange.append(num)
continue
}
if num - 1 != currentRange.last! { //if not next number in sequence, close range, start new
result.append(closeRange(currentRange))
currentRange = []
currentRange.append(num)
} else if num - 1 == currentRange.last {
currentRange.append(num) //if next number, add to range
}
}
if !currentRange.isEmpty {
result.append(closeRange(currentRange)) //check for unclosed ranges
}
return result
}
func closeRange(range: [Int]) -> String {
guard range.count > 0 else { return "" }
if range.count == 1 { return String(range.first!) }
return "\(range.first!)->\(range.last!)"
}
}
var test = Solution()
var input = [0,1,2,4,5,7]
var result = test.summaryRange(input)
print(result)
Let me know how this works for you!
I am working with arrays and I created a function that appends an array from within. However when I print the array, it still appears empty. What gives?
var queriesFinal : [String] = []
func queryValidator(search : String)
{
var letterSet = NSCharacterSet(charactersInString: "abcdefgjhijklmnopqrstuvwxyz ")
var numberSet = NSCharacterSet(charactersInString: "1234567890".uppercaseString)
var queriesTwo : [String] = search.lowercaseString.componentsSeparatedByCharactersInSet(letterSet)
for(var x = 0; x < queriesTwo.count; x++)
{
for(var y = 0; y < 10; y++)
{
var str = String(y)
if(queriesTwo[x] == str)
{
var numberStr = String(queriesTwo[x]) + "th"
queriesFinal.append(numberStr)
}
}
}
}
println(queriesFinal)
search = "Matt 8th"
queryValidator(search)
This code can run in playground..
I appreciate any help!
As mentioned by Mike S, you've made a small mistake println should be after your queryValidator, I've also added an optional in case your queryValidator search returns nil, also as mentioned by Zaph you don't need numberSet, so I removed it:
func queryValidator(search : String) -> [String]? {
let queriesTwo:[String] = search.lowercaseString.componentsSeparatedByCharactersInSet(NSCharacterSet(charactersInString: "abcdefgjhijklmnopqrstuvwxyz "))
var queriesResult:[String] = []
for x in 0...queriesTwo.count-1 {
for y in 0...9 {
if(queriesTwo[x] == String(y)) {
queriesResult.append(String(queriesTwo[x]) + "th")
}
}
}
return queriesResult.count > 0 ? queriesResult : nil
}
var search = "Matt 8 less7"
if let queriesFinal = queryValidator(search) {
println(queriesFinal)
} else {
println("no result")
}
An alternative approach with Regular Expressions:
func queryValidator(search: String) -> [String] {
var queriesFinal:[String] = []
var nsSearch: NSString = search
let pattern = "(\\d+)"
var regEx = NSRegularExpression(pattern:pattern, options:nil, error:nil)
regEx?.enumerateMatchesInString(nsSearch, options:nil, range:NSMakeRange(0, nsSearch.length), usingBlock: { (result, flags, stop) in
let found = nsSearch.substringWithRange(result.range)
queriesFinal.append("\(found)th")
})
return queriesFinal
}
var result = queryValidator(search)
println("result: \(result)")
Output:
result: [8th, 7th, 6th]
For information on regular expressions see: Regular Expressions