Scenario:
An array of strings, many are duplicated.
Goal:
Produce a UNIQUE array of strings.
Modus Operandi:
I was thinking of converting the array to a set of strings which become unique; from which to generate a new array of unique strings.
Question: How does one convert a Swift array into a Swift Set?
let nonUniqueArray = ["A", "B", "C", "C", "B", "A"]
let uniqueArray = Array(Set(nonUniqueArray))
print(uniqueArray)
produces
["C", "B", "A"]
Swift 2.2 produces exactly the same result as well.
Have you tried let myset = Set(myarray) ?
Related
This question already has an answer here:
Check if an array contains elements of another array in swift
(1 answer)
Closed 2 years ago.
I have 2 500,000 count arrays of strings. is there a more efficient way to check if they have elements that match then:
let array1 = ["a", "b", "c", "d", "e"]
let array2 = ["d", "e", "f", "g", "h"]
var maching = [0]
for element1 in array1 {
for element2 in array2 {
if element1 == element1 {
maching.append(element1)
}
}
}
Thanks in advance
If elements are Hashable (strings are) and if we can ignore duplicates and ordering, then using Set is the easiest solution:
let matching = Set(array1).intersection(Set(array2))
Depending on the nature of the data, we could come with an even better solution, e.g. an interval tree. The more information we have, the better solution can be designed. However, an optimal solution specific to one use case will be much more complex.
So this question is a follow up to this one: swift string permutations allowing the same strings
There, I asked about all possible mutations that I can make with a defined set of strings. What I am trying to do next is to filter out all results that have the same combination, but in a different order.
So if the input is: ["AB", "AC", "CA", "CB"], the output should be ["AB", "AC", "CB"], since "AC" and "CA" have the same building blocks.
So my thought was to first sort each string alphabetically, and maybe then create a Set.
I am already stuck on the first part :(
let array = ["AB", "AC", "DC", "CA", "CB"]
print(type(of: array))
print(array)
let sortedArray = array.map{ $0.sorted() }
print(type(of: sortedArray))
print(sortedArray)
The output is:
Array<String>
["AB", "AC", "DC", "CA", "CB"]
Array<Array<Character>>
[["A", "B"], ["A", "C"], ["C", "D"], ["A", "C"], ["B", "C"]]
While I expected for the sortedArray:
["AB", "AC", "CD", "AC", "BC"]
Then I thought to join the individual strings back together:
print(array.map{ $0.joined() } )
Resulting in ambiguous reference to member 'joined()'
But how to fix this I don't understand.
I also saw this one: swift sort characters in a string where the following code is used:
var nonSortedString = "5121"
var sortedString = String(Array(nonSortedString.characters).sort())
But I don't see how to apply that using map and friends (after converting to Swift 4)
Any help appreciated.
If you want to take a string, sort its characters, and build a new string from that, in Swift 4 you can:
let string = "foobar"
let sortedString = String(string.sorted())
That results in:
"abfoor"
So, going back to your original problem, you can take you strings, which are a collection of permutations, and build a sorted array of combinations like so:
let permutations = ["AB", "AC", "DC", "CA", "CB"]
// build set of combinations where each string has, itself, been sorted alphabetically
let combinations = Set(permutations.map { String($0.sorted()) })
// convert set (which removed duplicates) back to an array and sort it
let result = Array(combinations).sorted()
That results in:
["AB", "AC", "BC", "CD"]
A different approach...
This solution uses another reduce function implementation from the Sequence protocol
let reduced = array.map({ String($0.sorted()) }).reduce(into: [String]() ){ (result, element) -> Void in
if !result.contains(element)
{
result.append(element)
}
}.sorted()
print(reduced)
The result is...
["AB", "AC", "BC", "CD"]
I have an array of type "Option".
The class Optioncontains an element optionDetail.
The class optionDetail contains elements of detailTraits, which is an [String] with each string being called the detailTraitName.
So my structure of getting the detailTraits looks like Option -> optionDetail -> detailTraitswhich would return me [String], or Option -> optionDetail -> detailTraits -> detailTraitName, which would return me just one String
I would like to match up the detailTraits array with another array, named selectedDetails, which is an [String] and find the elements in which all of the selectedDetails are contained inside of the detailTraits. I then want to return all of the Option in which this situation is true.
For example, if my selectedDetails array contains ["A", "B"], and I have one detailTraits array that has ["A","C"] and one that has ["A"] and one that has ["A", "B", "C"], I just want to return the option which had detailTraits of ["A", "B", "C"]
My current code looks like the following:
newOptions = option.filter({ $0.optionDetail?.detailTraits.filter({ selectedDetails.contains($0.detailTraitName ?? "") }).count == selectedDetails.count })
Is there a better way to do this? This algorithm seems pretty inefficient since It's probably in the order of magnitude of N^3, but I can't think of a better way to look through an array of arrays and match it to another array.
Thank you!
You can optimise this by first filtering by comparing count on selectedDetails and detailTraits, and then comparing actual values. This way options set would be reduced to only those detailTraits having exact same count. For example you would only need to compare the string values with array containing exact 3 items (if selectedDetails is ["A", "B", "C"]), completely avoiding one iteration in loop.
Hope this helps
I am new to ruby and trying to create a method that takes a string and returns an array with each letter as their own index in an array.
def validate_word(word)
w=[]
word.downcase!
w << word.split(//)
return w
end
validate_word("abcABC")
=> [["a", "b", "c", "a", "b", "c"]]
I would like it to return
=>["a", "b", "c", "a", "b", "c"]
Thank you for looking at my code.
In your code you do not need to create a new array, since String#split returns array which you want. Also, Ruby returns last string of a method by default, so you can write:
def validate_word(word)
word.downcase!
word.split(//) # or you can chain methods: word.downcase.split('')
end
validate_word("abcABC")
=> ["a", "b", "c", "a", "b", "c"]
Note: do not use methods with exclamation mark (downcase!) except cases when you want modify source object. Use alternative methods(downcase) instead.
How to know how many times the same Object appears in Array?
I want to check how many times I found the object, like:
array = ['A','A','A','B','B','C','C','C','D']
So, A appeared three times, B twice, C three too, and only one for D.
I know that if I use "find_all", like:
array.find_all{ |e| array.count(e) > 1 }
I will get with answer
["A", "A", "A", "B", "B", "C", "C", "C"]
but, how I can count this? I want something like:
A = 3, B = 2, C = 3, D = 1.
You can use inject on the array to iterate over the array and pass a hash into each iteration to store data. So to retrieve the count of the array you gave you would do this:
array = ["A", "A", "A", "B", "B", "C", "C", "C"]
array.inject(Hash.new(0)) do |hash, array_item|
hash[array_item] += 1
hash # this will be passed into the next iteration as the hash parameter
end
=> {"A"=>3, "B"=>2, "C"=>3}
Passing in Hash.new(0) rather than {} will mean that the default value for each key when you first encounter it will be 0.