Change array string value from another array with index - arrays

I am trying to change my string value in an array after shuffling another array, how am i to do this?
Example:
var array1 = [1,2,3,4,5,6]
var stringarray = ["\\(array1[0]) = 1")
array1.shuffle()
print(stringarray)
How am i to change the original stringarray value to the new shuffled value?
Thank you
The task:
#IBAction func nextQuestion(_ sender: Any) {
if levelSelected == 1 {
questionLabel.text = standardRules.randomElement()
}
players.shuffle()
print(players)
standardRules has a string value that takes the value of players[0]
Essentially what i am trying to do is this:
I am trying to grab 2 random values that are not the same in a string like this
var players = ["Jack, John, Michael, Peter"]
var playersArray = ["\(players.randomElement) and \(players.randomElement) has to battle")
How am i to do this, so it grabs 2 different values?

You could make it very easy by this code :
var players = ["Jack", "John", "Michael", "Peter"]
// get the first random element
var random1 = players.randomElement()
//delete that element so you can't duplicate it
players = players.filter{$0 != random1}
//get your second radom element
var random2 = players.randomElement()
//add your element again
players.append(random1!)

Looks like you're missing some core concepts of the Swift language. When you create your stringarray it makes a call of array1.description and stores the result into an array. From that point any modifications of the original array will not change anything in stringarray.
So if you want to pick two different players from an array you need to do something like that:
let index1 = Int.random(in: (0 ..< players.count))
var index2: Int
repeat {
index2 = Int.random(in: (0 ..< players.count))
} while index1 == index2
let matchText = "\(players[index1]) and \(players[index2] has to battle)"

I would try replacing:
var stringarray = ["\\(array1[0]) = 1")
array1.shuffle()
with:
var stringarray = array1.shuffle()

Related

Merging arrays of dictionaries based on dates

I have 2 arrays, both of kind [[String:Any]] , where each element :
["date":Date,"value":CGFloat] //always looks like this
I might even have more than 2 (!)
I would like to create a single array with the same structure that sums all of them (2 or more) for each date that appears in all of them.
If the date of array1 does not appear on the others(array2, etc) I will simply add 0 to the value at array 1 for this specific date.
Is there a simple efficient way to do so ?
Instead of dictionaries use structs, it's more convenient:
struct MyStruct {
let date: Date
let value: CGFloat
}
Let's create 3 arrays of MyStructs:
let now = Date()
let later = now.addingTimeInterval(3600)
let earlier = now.addingTimeInterval(-3600)
let array1: [MyStruct] = [MyStruct(date: now, value: 1),
MyStruct(date: later, value: 2)]
let array2: [MyStruct] = [MyStruct(date: now, value: 3),
MyStruct(date: later, value: 4)]
let array3: [MyStruct] = [ MyStruct(date: earlier, value: 5),
MyStruct(date: later, value: 6)]
Now, let's group the elements and add the values for the elements with the same date property:
let allArrays = array1 + array2 + array3
let dict = Dictionary(allArrays.map { ($0.date, $0.value) },
uniquingKeysWith: { $0 + $1 })
All you have to do now is convert it back to an array of MyStruct:
let newArray = dict.map { MyStruct(date: $0.key, value: $0.value) }
And you can check the results like so:
for element in newArray {
print("date =", element.date, "value =", element.value)
}
I found a way, assuming data is inside a structure(not a dic) which is a better practice.
I will put all arrays into a single large array, sort it by dates, loop on it and as long as date is equal previous date(or close enough to equality), I will sum the values up. When the next date is different, I will save the date and the sum.
//create a combined array from all given arrays
var combined = [RootData]()
for list in dataSets {combined.append(contentsOf: list)}
//sort it by dates
let sortedArray = combined.sorted { $0.date < $1.date }
//new array - sum of all
var sumData = [RootData]()
var last:Date = sortedArray[0].date //set starting point
var sum:CGFloat = 0
for element in sortedArray
{
//same date - accumulate(same is less than 1 sec difference)
if(abs(element.date.seconds(from: last)) <= 1) {
sum+=element.value
}
//save
else {
sumData.append(RootData(value:sum,date:last))
sum=element.value
}
last=element.date
}
//last object
sumData.append(RootData(value:sum,date:last))
return averageData
Here RootData is a simple structure for the data with :
value:CGFloat
date:Date
Works as expected.
Because dates are not always completely equal , I check equality by assuming 1 second or less is the same date.

add multiple objects to swift array in for loop

for tempExportData in exportDataArray {
let tmpRegNO:NSString = (tempExportData as AnyObject).object(forKey: kRegisteredNo) as! NSString
print("tmpRegNO is",tmpRegNO)
var tmpNoArray:Array = [String]()
tmpNoArray.append(tmpRegNO as String)
print("Count is",tmpNoArray.count)
print("ARRAY is",tmpNoArray)
}
I am trying to add string value i.e tmpRegNO to the Array tmpNoArray.
In this I can able to add only one value to the array at a time.
How to add the next value to that array when it is looping for second time.
As already mentioned you have to declare the array before entering the loop.
Your code is very objectivecish. This is a swiftier version. Don't annotate types the compiler can infer and use key subscription rather than ugly casting to AnyObject and objectForKey:.
var tmpNoArray = [String]()
for tempExportData in exportDataArray {
let tmpRegNO = tempExportData[kRegisteredNo] as! String
print("tmpRegNO is",tmpRegNO)
tmpNoArray.append(tmpRegNO)
print("Count is",tmpNoArray.count)
print("ARRAY is",tmpNoArray)
}
You can even write the whole expression in one line:
let tmpNoArray = exportDataArray.flatMap { $0[kRegisteredNo] as? String }
You need move the tempNoArray initialization outside of your for in loop, if not the your array will be initialized once for every item in your exportDataArray remaining only the las item as consequence
You need something like this
var tmpNoArray:Array = [String]()
for tempExportData in exportDataArray{
if let tmpRegNO = tempExportData[kRegisteredNo] as? String
{
print("tmpRegNO is",tmpRegNO)
tmpNoArray.append(tmpRegNO as String)
print("Count is",tmpNoArray.count)
print("ARRAY is",tmpNoArray)
}
}

"Extra argument in call" error when using zip() to iterate over multiple arrays

I'm trying to iterate over multiple arrays then place everything into one other array.
This is my class that I'm going to loop into:
class Place {
var names = [String]()
var messages = [String]()
var latidudes = [Double]()
var longitudes = [Double]()
var locations = [CLLocationCoordinate2D]()
}
And this is my function:
private func placesArrayLoop() {
let CoffeeShopNames = ["aCoffee","bCoffee", "cCoffee"]
let messages = ["message0", "message1", "message2"]
let latitudes = [40.232320, 40.232321, 40.232322]
let longitudes = [-95.388069, -95.388068, 95.388067]
for (name, message, latitude, longitude) in zip(CoffeeShopNames, messages, latitudes, longitudes) {
let place = Place()
place.names.append(name)
place.messages.append(message)
place.latitudes.append(latitude)
place.longitudes.append(longitude)
}
}
It is giving me the error, "extra argument in call pointing to latitudes in the zip array line. I'm assuming it's a syntax error new to swift 3, but I've looked around and cant find how to fix it. But the code bellow works...
let strArr1 = ["Some1", "Some2", "Some3"]
let strArr2 = ["Somethingelse1", "Somethingelse2", "Somethingelse3"]
for (e1, e2) in zip(strArr1, strArr2) {
print("\(e1) - \(e2)")
}
So now I'm really confused.
The zip() function only takes two arguments (hence why your second example works).
http://swiftdoc.org/v3.0/func/zip/
You are trying to pass it four arguments.

swift - using .map on struct array

i have a struct array that i want "break up" into smaller arrays that can be called as needed or at least figure out how i can map the items needed off one text value.
the struct:
struct CollectionStruct {
var name : String
var description : String
var title : String
var image : PFFile
var id: String
}
and the array made from the struct
var collectionArray = [CollectionStruct]()
var i = 0
for item in collectionArray {
print(collectionArray[i].name)
i += 1
}
printing partArray[i].name gives the following result:
pk00_pt01
pk00_pt02
pk00_pt03
pk01_pt01
pk01_pt02
pk01_pt03
pk01_pt04
pk01_pt05
pk01_pt06
pk01_pt07
pk01_pt08
this is just some test values but there could be thousands of entries here so i wanted to filter the entire array just by the first 4 characters of [i].name i can achieve this by looping through as above but is this achievable using something like .map?
I wanted to filter the entire array just by the first 4 characters of
[i].name
You can achieve this by filtering the array based on the substring value of the name, as follows:
let filteredArray = collectionArray.filter {
$0.name.substring(to: $0.name.index($0.name.startIndex, offsetBy: 4)).lowercased() == "pk00"
// or instead of "pk00", add the first 4 characters you want to compare
}
filteredArray will be filled based on what is the compared string.
Hope this helped.
If you want to group all data automatically by their name prefix. You could use a reducer to generate a dictionary of grouped items. Something like this:
let groupedData = array.reduce([String: [String]]()) { (dictionary, myStruct) in
let grouper = myStruct.name.substring(to: myStruct.name.index(myStruct.name.startIndex, offsetBy: 4))
var newDictionart = dictionary
if let collectionStructs = newDictionart[grouper] {
newDictionart[grouper] = collectionStructs + [myStruct.name]
} else {
newDictionart[grouper] = [myStruct.name]
}
return newDictionart
}
This will produce a dictionary like this:
[
"pk00": ["pk00_pt01", "pk00_pt02", "pk00_pt03"],
"pk01": ["pk01_pt01", "pk01_pt02", "pk01_pt03", "pk01_pt04", "pk01_pt05", "pk01_pt06", "pk01_pt07"],
"pk02": ["pk02_pt08"]
]
Not sure if i am understanding you correctly but it sounds like you are looking for this...
To create a new array named partArray from an already existing array named collectionArray (that is of type CollectionStruct) you would do...
var partArray = collectionArray.map{$0.name}

Counting number of occurances in an Array

I want to count number of occurances in an array in ActionScript 3.0. Say I have
var item:Array = ["apples", "oranges", "grapes", "oranges", "apples", "grapes"];
How can I make it show the number of matching strings? For instance, result: apples = 2, oranges = 2 etc.
I got this code from another similar question:
private function getCount(fruitArray:Array, fruitName:String):int {
var count:int=0;
for (var i:int=0; i<fruitArray.length; i++) {
if(fruitArray[i].toLowerCase()==fruitName.toLowerCase()) {
count++;
}
}
return count;
}
var fruit:Array = ["apples", "oranges", "grapes", "oranges", "apples", "grapes"];
var appleCount=getCount(fruit, "apples"); //returns 2
var grapeCount=getCount(fruit, "grapes"); //returns 2
var orangeCount=getCount(fruit, "oranges"); //returns 2
In this code, if you want to get the count of say "apple". You need to set up variables for each item (var appleCount=getCount(fruit, "apples")). But what if you have hundreds and thousands of fruit names, it is not possible to write down new variables for each and every fruit.
I'm completely new to AS3 so forgive me. Please include clear comments in your code as I want to understand the code.
var item:Array = ["apples", "oranges", "grapes", "oranges", "apples", "grapes"];
//write the count number of occurrences of each string into the map {fruitName:count}
var fruit:String;
var map:Object = {}; //create the empty object, that will hold the values of counters for each fruit, for example map["apples"] will holds the counter for "apples"
//iterate for each string in the array, and increase occurrence counter for this string by 1
for each(fruit in item)
{
//first encounter of fruit name, assign counter to 1
if(!map[fruit])
map[fruit] = 1;
//next encounter of fruit name, just increment the counter by 1
else
map[fruit]++;
}
//iterate by the map properties to trace the results
for(fruit in map)
{
trace(fruit, "=", map[fruit]);
}
output:
apples = 2
grapes = 2
oranges = 2

Resources