I'm working with a framework and have to change some things for my project.
The original is
var tree:FBQuadTree? = nil
...
if tree == nil {
tree = FBQuadTree()
}
I need always a custom number of trees. So my consideration was that I use an array for this.
var tree:[FBQuadTree?] = []
...
if tree[number] == nil {
tree[number] = FBQuadTree()
}
But I don't know how to fill my new tree array. Sure I could do smth. like this:
let element:FBQuadTree?
layersTree.append(element)
Okay, but my problem is that number of elements isn't static. So sometimes there is just one element, sometimes a lot more.
Is that possible what I want to do?
the whole thing:
var array:[FBQuadTree] = []
//fill
for i in 0..<MyDynamicSize {
array.append(//how to fill?)
}
//give new values
for i in 0..<MyDynamicSize {
array[i] = FBQuadTree()
}
If you're just trying to get an Array of a myDynamicSize* number of FBQuadTree instances, you can use init(repeating:count:).
var array = [FBQuadTree](count: myDynamicSize, repeatedValue: FBQuadTree())
Sidenote: by convention, types start with capitals, whereas variable names start with lowercase letters. So myDynamicSize, rather than MyDynamicSize
please try this
var array:[FBQuadTree?] = []
//fill
for i in 0..<MyDynamicSize {
array.append(nil)
}
Related
I dont know how doint that. I try find replacement obj method
indexOfObject on the swift but not find
i have array = [1,3,6,2,3] and input in array value 3, i am need find repeating value with min index from array. Answer with index 1. How do it?
You have to loop through the entire collection, for each item, see if we had seen this before. And as we are doing that, let’s keep track of the index of the first item that has been repeated somewhere in the collection, to see if this is the first repeated item or not:
extension Collection where Element: Hashable {
func indexOfFirstRepeated() -> Index? {
var result: Index? // the index of the first item repeated anywhere else in the collection
var firstOccurrences: [Element: Index] = [:] // dictionary to keep track of the first item that every element was first encountered in the collection
for (index, element) in zip(indices, self) {
if let firstOccurrence = firstOccurrences[element] { // find previous occurrence of this value, if any
if let previousLowestIndex = result { // if we found this element before, let's see if we had already found another repeated element
if firstOccurrence < previousLowestIndex { // if so, let’s see if the first occurrence of this element occurred before the first occurrence of the previously discovered repeated element
result = firstOccurrence
}
} else { // otherwise, no prior repeated element found, so this is our first repeated element found thus far
result = firstOccurrence
}
} else {
firstOccurrences[element] = index // if we got here, this is the first time we've seen this element, so record the index of this first occurrence
}
}
return result
}
}
Thus:
let array = [9,8,7,1,3,6,2,3,1]
if let index = array.indexOfFirstRepeated() {
print(index) // 3
}
Now, obviously, as we iterate through this array, the value 3 is the first value that we will see repeated, but that doesn’t matter, because the repeated value 1 will be found at the very end of the array, and 1’s first index is lower than 3’s first index.
Two observations on the above:
I made it generic, so that it works on any hashable type, e.g.:
let array = ["bill", "sam", "susan", "sam", "bill"]
if let index = array.indexOfFirstRepeated() {
print(index)
} else {
print("not found")
}
I made this a Collection extension (rather than an Array extension) so that it would work on other collection types (e.g. array slices, etc.). You can make it an Array extension, just as easily, but we prefer to use the most abstract type that is convenient, to make it as flexible as possible.
This is basically a riff on uniqued.
import Algorithms
public extension BidirectionalCollection where Element: Hashable {
var firstDuplicate: (index: Index, element: Element)? {
var set: Set<Element> = []
return indexed().reversed().reduce(into: nil) {
if !set.insert($1.element).inserted {
$0 = $1
}
}
}
}
You can get the last duplicate by not reversing before reducing.
Assume you have an array of n integers, with a[i] = i, except that a[1] = a[2] = 1, and I may or may not have have changed a[i] = 0 for some i >= 2.
The smallest index of a duplicate element is either 0 or 1. To find out which you have to find the i >= 2 with a[i] = 0 or find that no such i exists. So you have to visit all array elements.
and good job , well basically i have array like this :
let imageArray = [ ["image0"] , ["image11","image12"] , ["image2"], ["image31","image32","image33"] ]
In this point i want to put for example first item of each nested array into a new array like this :
var newArray = ["image0","image11","image2","image31"]
And also i want to have a condition for example if "image31" clicked we have a new page that show ervery images of that first array show us, like ["image31", "image32", "image33"]
So could you tell any idea how can implement like this?
You can try
let res = imageArray.map { $0.first! }
When clicked use the index to access other elements , say from above index 3 image is clicked then use
let resImages = imageArray[clickedIndex]
Edit:
let arr = ["images/product/2021-05-02T09-47-17.699Z-download (2).jpg"]
let res = arr.map { $0[$0.range(of: "images/product/")!.upperBound...] }
print(res)
Using simple data structures (like arrays) to model complex data is rarely the best approach.
In this case I would create a struct ImageList and then create an array of this struct
struct ImageList {
let images: [String]
var firstImage: String? {
return self.images.first
}
}
You can use map to create the array from your current source, if required
imageListArray = imageArray.map { ImageList(images:$0) }
Now you can have an index that is associated with an ImageList struct - imageListArray[i].firstImage! is the value you want for your list and iageListArray[i].images is the array you want for your second requirement.
I am trying to shuffle my arrays using the following extension:
extension Array {
var shuffled: [Element] {
guard count > 1 else { return self }
var elements = self
for index in indices {
let newIndex = Int(arc4random_uniform(UInt32(elements.count - index))) + index
guard index != newIndex else { continue }
swap(&elements[index], &elements[newIndex])
}
return elements
}
}
I am then using this code to shuffle and get the first 20 items on my plist:
var questionsArray = [myPlistArray?.shuffled]
let shuffledQuestions = questionsArray.shuffle() // instance member cannot be used on type 'myViewController'
let first20 = questionsArray.prefix(20)
However, I always get this error:
// instance member cannot be used on type ‘myViewController’
Does anyone know how to do it right?
Or does anyone know how can I shuffle pList items and get the first 20 items?
My questions is quite the same with this one: How to return first 5 objects of Array in Swift?, however, my data is in a plist dictionary file...
Anyways, my pList file is this: myPlistArray.plist
Your 3 lines that are supposed to shuffle the array is jumbled and doesn't make much sense.
var questionsArray = [myPlistArray?.shuffled]
That line creates an array containing a single element, a shuffled version of myPlistArray. So you have an array within an array, which doesn't make sense.
let shuffledQuestions = questionsArray.shuffle() // instance member cannot be used on type 'myViewController'
That line tries to call a method shuffle() (not shuffled, shuffle, which doesn't exist) on the screwy shuffledQuestions array-within-array you created in the previous line.
let first20 = questionsArray.prefix(20)
That line would actually make sense if your first 2 lines were well formed.
You just want this:
let questionsArray = myPlistArray?.shuffled //Create a shuffled version
let first20 = questionsArray.prefix(20) //take the first 20 items.
That code should work assuming that myPlistArray is an optional array.
So I have two arrays a name array and a values array they are a string and double respectively. I want to be able for a user to type in a textfield and to iterate though the name array until there is a match then output the value that has the same number as the name to be outputted
this is the code i have:
for(var i = 0; i<name.count; i++){
if name[i] == typeFood{
yieldOutput == percent[i]
}
}
First, use find to locate the location of the value in the name array, then use the returned index to look up the percent:
if let idx = find(name, typeFood) {
yieldOutput = percent[idx]
}
You can also combine the two actions together with map to declare an output variable using let:
if let foodPercentage = find(name, typeFood).map({ percent[$0] }) {
// foodPercentage will have a value here
}
else {
// not-found logic here
}
I’m new to Swift and have been having some troubles figuring out some aspects of Arrays and Dictionaries.
I have an array of dictionaries, for which I have used Type Aliases - e.g.
typealias myDicts = Dictionary<String, Double>
var myArray : [myDicts] = [
["id":0,
"lat”:55.555555,
"lng”:-55.555555,
"distance":0],
["id":1,
"lat": 44.444444,
"lng”:-44.444444,
"distance":0]
]
I then want to iterate through the dictionaries in the array and change the “distance” key value. I did it like this:
for dict:myDicts in myArray {
dict["distance"] = 5
}
Or even specifically making sure 5 is a double with many different approaches including e.g.
for dict:myDicts in myArray {
let numberFive : Double = 5
dict["distance"] = numberFive
}
All my attempts cause an error:
#lvalue $T5' is not identical to '(String, Double)
It seems to be acting as if the Dictionaries inside were immutable “let” rather than “var”. So I randomly tried this:
for (var dict:myDicts) in myArray {
dict["distance"] = 5
}
This removes the error and the key is indeed assigned 5 within the for loop, but this doesn't seem to actually modify the array itself in the long run. What am I doing wrong?
The implicitly declared variable in a for-in loop in Swift is constant by default (let), that's why you can't modify it directly in the loop.
The for-in documentation has this:
for index in 1...5 {
println("\(index) times 5 is \(index * 5)")
}
In the example above, index is a constant whose value is automatically
set at the start of each iteration of the loop. As such, it does not
have to be declared before it is used. It is implicitly declared
simply by its inclusion in the loop declaration, without the need for
a let declaration keyword.
As you've discovered, you can make it a variable by explicitly declaring it with var. However, in this case, you're trying to modify a dictionary which is a struct and, therefore, a value type and it is copied on assignment. When you do dict["distance"] = 5 you're actually modifying a copy of the dictionary and not the original stored in the array.
You can still modify the dictionary in the array, you just have to do it directly by looping over the array by index:
for index in 0..<myArray.count {
myArray[index]["distance"] = 5
}
This way, you're sure to by modifying the original dictionary instead of a copy of it.
That being said, #matt's suggestion to use a custom class is usually the best route to take.
You're not doing anything wrong. That's how Swift works. You have two options:
Use NSMutableDictionary rather than a Swift dictionary.
Use a custom class instead of a dictionary. In a way this is a better solution anyway because it's what you should have been doing all along in a situation where all the dictionaries have the same structure.
The "custom class" I'm talking about would be a mere "value class", a bundle of properties. This was kind of a pain to make in Objective-C, but in Swift it's trivial, so I now do this a lot. The thing is that you can stick the class definition for your custom class anywhere; it doesn't need a file of its own, and of course in Swift you don't have the interface/implementation foo to grapple with, let alone memory management and other stuff. So this is just a few lines of code that you can stick right in with the code you've already got.
Here's an example from my own code:
class Model {
var task : NSURLSessionTask!
var im : UIImage!
var text : String!
var picurl : String!
}
We then have an array of Model and away we go.
So, in your example:
class MyDict : NSObject {
var id = 0.0
var lat = 0.0
var lng = 0.0
var distance = 0.0
}
var myArray = [MyDict]()
let d1 = MyDict()
d1.id = 0
d1.lat = 55.55
d1.lng = -55.55
d1.distance = 0
let d2 = MyDict()
d2.id = 0
d2.lat = 44.44
d2.lng = -44.44
d2.distance = 0
myArray = [d1,d2]
// now we come to the actual heart of the matter
for d in myArray {
d.distance = 5
}
println(myArray[0].distance) // it worked
println(myArray[1].distance) // it worked
Yes, the dictionary retrieved in the loop is immutable, hence you cannot change.
I'm afraid your last attempt just creates a mutable copy of it.
One possible workaround is to use NSMutableDictionary:
typealias myDicts = NSMutableDictionary
Have a class wrapper for the Swift dictionary or array.
class MyDictionary: NSObject {
var data : Dictionary<String,Any>!
init(_ data: Dictionary<String,Any>) {
self.data = data
}}
MyDictionary.data