I have an array that is created like this in Swift
class TableViewCell: UITableViewCell, TKChartDelegate {
var xAxisDates = [] --> filled with fetch from Coredata
var yAxisValues = [] --> filled with fetch from Coredata
var maximumValue = maxElement(yAxisValues) -> error: TableViewCell.Type' does not have a member named 'yAxisValues'
func chart (){
var dataPointSeries = [TKChartDataPoint]()
for var i = 0; i < xAxisDates.count; ++i {
dataPointSeries.append(TKChartDataPoint(x: xAxisDates[i], y: yAxisValues[i]))
println(dataPointSeries)
}
<--more code setting up the chart-->
}
The console output is this:
[x = '2014-11-25 02:00:00 +0000', y = '61', name = '(null)', x = '2014-11-25 02:00:00 +0000', y = '57', name = '(null)']
I would like to find the max and min value of the y's.
I have tried maxElement(dataPointSeries(x)), but that does not work. Any idea how I could do this? I can't seem to find any solution.
All you want is the minimum and maximum values of the y elements, there is no need to consider this in the context of the multi-dimensional array. All you need do is:
let minimumYValue = minElement(yAxisValues)
let maximumYValue = maxElement(yAxisValues)
Related
I have a date in string format as:
var x = '2017-07-11 12:00';
var timeZone = 'America/New_York'
Now how can I format date according to timeZone? What I am expecting is:
var y = someMagicalFunction(x,timeZone)
// y = '2017-07-10 14:30'
Also reverse of it:
var x = reverseOfMagicalFunction(y, 'Asia/Kolkata');
// x = '2017-07-11 12:00';
I have used moment.tz to get results when x was of type Date.
var x1 = x.toISOString();
var y = moment.utc(x).tz(timezone).format('YYYY/MM/DD hh:mm:ss');
but was not able to get ReverseMagicalFucntion in that case. Any help?
When you are using momentjs, you can try something like (Check Here):
moment(date).tz('Europe/Berlin').format(format);
I have a LineChartDataSet from which I can get the yMax & yMin values like so:
let max = lineDataSet.yMax
let min = lineDataSet.yMin
With the older version (2.3) of the Charts Library, I could get the y-values as an array and find the index of the highest value like so:
let values = lineDataSet.yVals
let index = values.index(of: yMax)
How can I get the x value of the max y-value in the LineChartDataSet?
So if the max value in my DataSet is 100, how can I get the associated x-value?
(The new version 3.0, does not let me get the y-values as an array anymore)
You can still do the same:
let entries = lineDataSet.values
let index = entries.map { $0.y }.index(of: yMax)
or
let entries = lineDataSet.values
let index = entries.index(where: { $0.y == yMax })
After working on this problem for a bit, this is what I came up with:
for i in 0 ..< lineDataSet.entryCount {
let value = lineDataSet?.entryForIndex(i)
if value?.y == lineDataSet.yMax {
xValueOfyMax = (value?.x)!
break
}
}
The same thing can be done to find the min value.
If you need to find the most recent x-value (since there may be more than one value that matches), you can reverse the for-loop like this:
for i in (0 ..< lineDataSet.entryCount).reversed() {
etc...
}
I have the following for loop in Objective C code and am trying to transfer it to Swift.
double lastAx[4],lastAy[4],lastAz[4];
for (int i = 0; i < 4; ++i){
lastAx[i] = lastAy[i] = lastAz[i] = 0;
}
My Code so far gives me the error: Type Double has no subscript members
var lastAx:Double = 4
var lastAy:Double = 4
var lastAz:Double = 4
for i: Int32 in 0 ..< 4 {
lastAx[i] = lastAy[i] = lastAz[i] = 0
}
What am I missing? Help is very appreciated.
Declare lastAx, lastAy, lastAz as arrays with init(count:repeatedValue:) initializer:
var lastAx = [Double](count:4, repeatedValue: 0)
var lastAy = [Double](count:4, repeatedValue: 0)
var lastAz = [Double](count:4, repeatedValue: 0)
Also you will not have to zero them because these initializers set all of the values to zeros. You won't need the loop from the original code, so just delete it.
The question is related to calculating an increase in currency.
Loop over this n times, and let's say you start with $50k and your multiplier is 2. Something like b * 2 + a
This is the correct result:
$50,000.00
$100,000.00
$250,000.00
$600,000.00
$1,450,000.00
$3,500,000.00
$8,450,000.00
$20,400,000.00
$49,250,000.00
So just to be clear, the question is about efficiency in swift, not simply how to calculate this. Are there any handy data structures that would make this faster? Basically I was just looping through how many years (n) adding 2 (200%) and incrementing a couple temp variables to keep track of the current and previous values. It feels like there has got to be a much better way of handling this.
$50k base
$50k * 2 + 0 (previous value) = $100k
$100k * 2 + $50k = $250k
$250k * 2 + $100k = $600k
etc.
Code:
let baseAmount = 50000.0
let percentReturn = 200.0
let years = 10
// Calc decimal of percent.
var out: Double = 0.0
var previous: Double = 0.0
let returnPercent = percentReturn * 0.01
// Create tmp array to store values.
var tmpArray = [Double]()
// Loop through years.
for var index = 0; index < years; ++index
{
if index == 0
{
out = baseAmount
tmpArray.append(baseAmount)
}
else if index == 1
{
out = (out * returnPercent)
tmpArray.append(out)
previous = baseAmount
}
else
{
let tmp = (tmpArray.last! * returnPercent) + previous
previous = tmpArray.last!
tmpArray.append(tmp)
}
}
println(tmpArray)
Here are some ideas for improving efficiency:
Initialize your array to the appropriate size (it isn't dynamic; it is always the number of years)
Remove special cases (year 0 and 1 calculations) from the for-loop
Code:
func calculate(baseAmount: Double, percentReturn: Double, years: Int) -> [Double] {
// I prefer to return an empty array instead of nil
// so that you don't have to check for nil later
if years < 1 {
return [Double]()
}
let percentReturnAsDecimal = percentReturn * 0.01
// You know the size of the array, no need to append
var result = [Double](count: years, repeatedValue: 0.0)
result[0] = baseAmount
// No need to do this in the loop
if years > 1 {
result[1] = baseAmount * percentReturnAsDecimal
}
// Loop through years 2+
for year in 2 ..< years {
let lastYear = result[year - 1]
let yearBeforeLast = result[year - 2]
result[year] = (lastYear * percentReturnAsDecimal) + yearBeforeLast
}
return result
}
Efficiency in terms of speed I found this to be the fastest implementation of your algorithm:
let baseAmount = 50000.0
let returnPercent = 2.0
let years = 10
// you know the size of the array so you don't have to append to it and just use the subscript which is much faster
var array = [Double](count: years, repeatedValue: 0)
var previousValue = 0.0
var currentValue = baseAmount
for i in 0..<years {
array[i] = currentValue
let p2 = currentValue
currentValue = currentValue * returnPercent + previousValue
previousValue = p2
}
print(array)
Here is my problem.
I'm doing a little weather web app in flash.
So i read an xml feed and copose an array of data from it.
my xml is like this
<xml>
<prevision>
<date>22</date>
<hour>5</hour>
<temperature>40</temperature>
</prevision>
<prevision>
<date>22</date>
<hour>10</hour>
<temperature>44</temperature>
</prevision>
<prevision>
<date>22</date>
<hour>14</hour>
<temperature>45</temperature>
</prevision>
<prevision>
<date>22</date>
<hour>20</hour>
<temperature>37</temperature>
</prevision>
</xml>
So here is what i'm doing with my Actionscript 2
//**************************************
// Here i'm getting the current hour
var mytime = new Date();
var currenthour = mytime.getHours();
//*************************************
// Here i'm getting my XML
var myhour:Array = new Array();
var myxml:XML = new XML();
myxml.ignoreWhite = true;
myxml.onLoad = function(success)
{
dataextractor = myxml.firstChild.childNodes;
for (var j = 0; j < dataextractor.length; j++)
{
myhour.push(dataextractor[j].childNodes[1].firstChild.nodeValue);
}
// Doing this
trace(mydate);
}
// Will return this
// 5 , 10, 14 , 20
Now what i would like to do is to find and trace the entry in mydate array which have a a value that approach the most to "currenthour" variable (which is my current time i'm getting upper).
For exemple if currenthour = 11
In the case that i have myhour array equal to 5 , 10 , 14 , 20
The best match will be myhour[1]
Can someone help to do so?
myhour Array don't have a fixed number of entries.
Sometime it can be 5, 10, 14 and other time just 14,20 etc
Thanks a lot,
I'm not sure, if I got your idea. Do you need to find the nearest number to currenthour from myhour array?
That's it:
var minDiff : int = 12;
var diff : int;
var index : int = 0;
for (var i : int = 0; i < myhour.length; i++)
{
diff = Math.abs(myhour[i] - currenthour);
if (diff > 12)
diff = 24 - diff;
if (diff < minDiff)
{
minDiff = diff;
index = i;
}
}
myhour[index] is the result. Hope, I got an idea.
Imagine your numbers on a line, from 0 to 24.
Using a variable to keep track of the smallest distance between the current hours and each hour in your XML, you can find the index of the node you're looking for:
import mx.xpath.XPathAPI;
var myxml:XML = new XML();
myxml.ignoreWhite = true;
myxml.onLoad = function(loaded:Boolean) {
if (loaded) {
var hoursMin:Number = 24;
var hoursNow:Number = new Date().getUTCHours();
var hourID:Number;
var hours:Array = XPathAPI.selectNodeList(this.firstChild, "xml/prevision/hour");
var hoursNum:Number = hours.length;
for(var i:Number = 0 ; i < hoursNum; i++){
var hoursDiff:Number = Math.abs(hoursNow - parseInt(hours[i].firstChild));//look for the 'shortest distance' within 24 numbers
if(hoursDiff < hoursMin){//found the smallest current value
hoursMin = hoursDiff;//update the minimum
hourID = i;//store the node ID
}
}
trace(this.firstChild.childNodes[hourID]);//access the closest node in time
} else {
trace("XML Load Error!!");
}
}
myxml.load("feed.xml");
Here's the same thing without XPath, although I find accessing nodes a bit harder this way:
var myxml:XML = new XML();
myxml.ignoreWhite = true;
myxml.onLoad = function(loaded:Boolean) {
if (loaded) {
var hoursMin:Number = 24;
var hoursNow:Number = new Date().getUTCHours();
var hourID:Number;
var hoursNum:Number = this.firstChild.childNodes.length;
for(var i:Number = 0 ; i < hoursNum; i++){
var hoursDiff:Number = Math.abs(hoursNow - parseInt(this.firstChild.childNodes[i].childNodes[1].firstChild));//look for the 'shortest distance' within 24 numbers
if(hoursDiff < hoursMin){//found the smallest current value
hoursMin = hoursDiff;//update the minimum
hourID = i;//store the node ID
}
}
trace(this.firstChild.childNodes[hourID]);//access the closest node in time
} else {
trace("XML Load Error!!");
}
}
myxml.load("feed.xml");
HTH