I want to order an array with the help of another, like this:
var names = [anna, berta, caesar, dora]
var sorting = [2, 0, 1, 3]
to be sorted like this:
var sortedNames = [caesar, anna, berta, dora]
so that the Integer array ("sorting") sorts the String array ("names") after its own values. How can I do that?
I tried it with a for loop, but it didn't worked.
for i in 0...names.count
{
let x = "\(names[sorting]])"
sortedNames.append(x)
}
return history
You can use the map() function to transform the values of sorting:
var names = ["anna", "berta", "caesar", "dora"]
var sorting = [2, 0, 1, 3]
let sortedNames = sorting.map({ names[$0] }) // ["caesar", "anna", "berta", "dora"]
Keep in mind that this solution only works if the values in sorting are valid indices for the names array.
You can create a new object which has properties the names and sorting
var name: String!
var sorting: Int!
Then you can easily sort your array of objects like this
array.sort(by: {$0.sorting<$1.sorting})
In this way you will have for each name sorting value and it will be pretty easy to do any manipulations with it.
var names = [anna, berta, caesar, dora]
var sorting = [2, 0, 1, 3]
Simple approach with for loop is to select the values from sorting array and treat them as index to get respective value from names array.
var sortedNames = [String]()
for i in 0..<sorting.count {
let x = sortedNames[i]
sortedNames.append(x)
}
return sortedNames // [caesar, anna, berta, dora]
Related
In Swift I have an array of indices that I want to use to permute an array of values (very easy to do in Matlab), but can't figure out a simple way of doing it (using a for-loop would be easy, but I'm looking for a more efficient method).
For example:
var indices = [1,0,2]
var values = ["A","B","C"]
var permute = values[indices]
// Hoping to print: permute = ["B","A","C"]
var indices = [1,0,2]
var values = ["A","B","C"]
var permute = indices.map({values[$0]})
print(permute)
An alternative solution using compactMap,
let indices = [1, 0, 2]
var values = ["A", "B", "C"]
let permute = indices.compactMap({ values[$0] })
print(permute)
let indices = [1,0,2]
let values = ["A","B","C"]
var result: [String] = []
indices.forEach({ result.append(values[$0]) })
print(result) //["B", "A", "C"]
You can just map the keys array to the values array.
var keys = [1,0,2]
var values = ["a","b","c"]
print(keys.map({values[$0]}))
Let's say array A holds this:
[0, 1, 8, 3, 10, 6, 2]
And array B holds this:
[1, 2]
How can I generate a random index in array A which value does not appear in array B? Possible indexes in above example are:
0, 2, 3, 4, 5
But how to do this in Swift?
When you want to work with Array elements and their indices, enumerated() can be a good tool:
var a = [0, 1, 8, 3, 10, 6, 2]
var b = [1, 2]
var possibleIndices = a.enumerated()
.filter{!b.contains($0.element)}
.map{$0.offset}
print(possibleIndices)
//->[0, 2, 3, 4, 5]
(When b can be large, better make it a Set.)
And then:
(When we can assume b never holds all contents of a.)
var randomIndexToPossibleIndices = Int(arc4random_uniform(UInt32(possibleIndices.count)))
var randomIndex = possibleIndices[randomIndexToPossibleIndices]
If the assumption above cannot be satisfied, possibleIndices can be empty. So you'd better make randomIndex Optional:
var randomIndex: Int? = nil
if !possibleIndices.isEmpty {
var randomIndexToPossibleIndices = Int(arc4random_uniform(UInt32(possibleIndices.count)))
randomIndex = possibleIndices[randomIndexToPossibleIndices]
}
Thanks for Martin R.
First, you'd have to generate a diff between the 2 arrays ( unless they're both extremely large, in which case randomly trying recursively might result in better performance ).
Then all you have to do is find a random index you'd like to use and access said element:
#if os(Linux)
let j = Int(random() % ((count-1)))
#else
let j = Int(Int(arc4random()) % ((count-1)))
#endif
Will give you a proper index
If you then use this index and the element to find original element in your array you'll have your result.
If in case your elements are integers, and thus collisions can occur the thing I'd do would be recursively finding it to solve your problem. Remember that this can result in slow performance.
Look into the functional programming part of collections in swift here:
Swift Guide to map filter reduce
For instance you could use filter in the following way ( and I don't know if this is the best way ):
collection.filter {
var found = false;
for element in bCollection {
if element == $0 {
found = true;
}
}
return !found; // Might be better to turn true/false thing around in the above code to slightly improve performance.
}
How about working with sets?
let a = [0, 1, 8, 3, 10, 6, 2]
let b = [1, 2]
var setA = Set(a)
var setB = Set(b)
setA.subtract(setB)
var index: Int? = nil
if let first = setA.first {
index = a.index(of: first)
}
// if index == nil no such index exists
var arrayValues = [[2,3,5],[3,5]]
var commonArrayValues = _.intersection(arrayValues);
Currently it is working as,
_.intersection([[2,3,5],[3,5]])
Result: [2,3,5]
But it should work as, (i.e outer array should be removed)
_.intersection([2,3,5],[3,5])
Expected Result: [3,5]
Anyone kindly give me a proper solutions. Thank you in advance.
You can use apply with intersection to get what you want:
var result = _.intersection.apply(null, arrayValues);
var arrayValues = [[2,3,5],[3,5], [2,3,5,6]]
var result = _.intersection.apply(null, arrayValues);
document.getElementById('results').textContent = JSON.stringify(result);
<script src="https://cdnjs.cloudflare.com/ajax/libs/underscore.js/1.8.2/underscore.js"></script>
<pre id="results"></pre>
intersection *_.intersection(arrays)
Computes the list of values that are the intersection of all the arrays. Each value in the
result is present in each of the arrays.
_.intersection([1, 2, 3], [101, 2, 1, 10], [2, 1]);
=> [1, 2]
var arrayValues = [[2,3,5],[3,5]]
Here arrayValues is an array having 2 arrays. Where as _.intersection expects arrays as parameter and not an array having arrays.
_.intersection([2,3,5],[3,5])
Or
_.intersection(arrayValues[0],arrayValues[1])
will output as what you need.
The only way I can think of is using eval:
var arrayValues = [[2,3,5],[3,5]]
var evalString = '_.intersection(';
arrayValues.forEach(function (element, index){
evalString += 'arrayValues['+index+'],';
});
evalString =evalString.slice(0, -1);
evalString += ');'
eval(evalString);
evalString would end being something like _.intersection(arrayValues[0],arrayValues[1],...,arrayValues[n]);
I am kinda stumped on figuring this out. I want to populate an array with the string values that comes from a for-in loop.
Here's an example.
let names = ["Anna", "Alex", "Brian", "Jack"]
for x in names {
println(x)
}
The current x value would generate 4 string values (Anna, Alex, Brian, Jack).
However I need some advice in going about getting these four values back into an array. Thank you in advance.
Whatever is on the right side of a for - in expression must be a SequenceType. Array, as it happens, can be initialised with any SequenceType. So if you're just doing something like this:
var newArray: [String] = []
for value in exoticSequence {
newArray.append(value)
}
The same thing can be accomplished (faster), by doing this:
let newArray = Array(exoticSequence)
And it doesn't matter what type exoticSequence is: if the for-in loop worked, Array() will work.
However, if you're applying some kind of transformation to your exoticSequence, or you need some kind of side effect, .map() might be the way to go. .map() over any SequenceType can return an array. Again, this is faster, and more clear:
let exoticSequence = [1, 2, 3]
let newArray = exoticSequence.map {
value -> Int in
// You can put whatever would have been in your for-in loop here
print(value)
// In a way, the return statement will replace the append function
let whatYouWouldHaveAppended = value * 2
return whatYouWouldHaveAppended
}
newArray // [2, 4, 6]
And it's equivalent to:
let exoticSequence = [1, 2, 3]
var newArray: [Int] = []
for value in exoticSequence {
print(value)
let whatYouWouldHaveAppended = value * 2
newArray.append(whatYouWouldHaveAppended)
}
newArray // [2, 4, 6]
I want to get a range of objects from an array. Something like this:
var array = [1,3,9,6,3,4,7,4,9]
var newArray = array[1...3] //[3,9,6]
The above would access elements from index 1 to 3.
Also this:
newArray = array[1,5,3] // [3,4,6] would be cool
This would retrieve elements from index 1, 5 and 3 respectively.
That last example can be achieved using PermutationGenerator:
let array = [1,3,9,6,3,4,7,4,9]
let perms = PermutationGenerator(elements: array, indices: [1,5,3])
// perms is now a sequence of the values in array at indices 1, 5 and 3:
for x in perms {
// iterate over x = 3, 4 and 6
}
If you really need an array (just the sequence may be enough for your purposes) you can pass it into Array's init method that takes a sequence:
let newArray = Array(perms)
// newArray is now [3, 4, 6]
For your first example - with arrays, that will work as-is. But it looks from your comments like you're trying it with strings as well. Strings in Swift are not random-access (for reasons relating to unicode). So you can't use integers, they have an String-specific bidirectional index type:
let s = "Hello, I must be going"
if let i = find(s, "I") {
// prints "I must be going"
println(s[i..<s.endIndex])
}
This works :
var n = 4
var newArray = array[0..<n]
In any case in
Slicing Arrays in Swift you'll find a very nice sample of the Python slice using a extension to Arrays in Swift.