I loop through an Array and every time a found an object with the category equal to 1 I want to check if there is another object in the rest of the array with this category. I wrote this method
func getNextIndex(startIndex:Int , t : [Client]) -> Int{
var index = startIndex
while(index < t.count && Int(t[index].category!) != 1){
index += 1
}
if(t[index].category == 1){
return index
}else{
return -1
}
}
This return always the same index I use to call the method. If I call it with index+1 the app crashes in the line if(t[index].category == 1)
The behavior you describe is exactly what one would expect from this code.
When you fall out of your "while" loop, either you've found another entry or index has passed the end of the array. The latter case is what is causing your crash.
There are many ways to code this, but to keep your code mostly the same, after the loop, simply test if index is less than t.count. If it is, you have found what you are looking for, return index. If not, then you have gone all the way through the loop without finding what you are looking for, so return -1.
Loop condition ends the iteration in two situations:
When t[index].category is 1 - this is the situation that you are looking for, and your code is handling it.
When index reaches the end of the array - this is the situation when the desired item is not found; you code does not handle this condition, that's why your app crashes.
To fix this, and also to look for the item after the current index, change the code as follows:
func getNextIndex(startIndex:Int , t : [Client]) -> Int {
var index = startIndex
while(index < t.count && Int(t[index].category!) != 1){
index += 1
}
if index == t.count {
return -1
}
// Otherwise, category is 1. Continue searching
while(index < t.count && Int(t[index].category!) != 1){
index += 1
}
return index != t.count ? index : -1
}
Related
I have skip list contains an ADC, FIFO, DAC, FILO etc.
I want to know whether these words are used in the entire module or not .if used in the module should return the unused words.
I have a program but it is taking too much time to execute.
Please help me with this.
Here is the code :
Skip Search_In_Entire_Module(Skip List)
{
int sKey = 0
Skip sList = create()
string data = ""
string objText1
Object obj
for data in List do
{
int var_count = 0
for obj in m do
{
objText1 = obj."Object Text"
if objText1!=null then
{
if (isDeleted obj){continue}
if (table obj) {continue}
if (row obj) {continue}
if (cell obj) {continue}
Buffer buf = create()
buf = objText1
int index = 0
while(true)
{
index = contains(buf, data, index)
if(0 <= index)
{
index += length(data)
}
else
{
var_count++
break
}
}
delete(buf)
}
}
if (var_count ==0)
{
put(sList,sKey,data)
sKey++
}
}
return sList
}
Unused_Terminolody_Data = Search_In_Entire_Module(Terminology_Data)
Just wondering: why is this in a while loop?
while(true)
{
index = contains(buf, data, index)
if(0 <= index)
{
index += length(data)
}
else
{
var_count++
break
}
}
I would instead just do:
index = contains ( buf, data )
if ( index == -1 ) {
var_count++
}
buf = ""
I would also not keep deleting and recreating the buffer. Create the buffer up where you create the object variable, then set it equal to "" to clear it, then delete it at the end of the program.
Let me know if this helps!
Balthos makes good points, and I think there's a little more you could do. My adaptation of your function follows. Points to note:
I implemented Balthos's suggestions (above) of taking out the
'while' loop, and buffer creation/deletion.
I changed the function signature. Given that Skip lists are passed
by reference, and must be created and deleted outside the function
it's syntactically confusing (to me, anyway) to return them from a
function. So, I pass both skip lists (terms we're seeking, terms not
found) in as function parameters. Please excuse me changing variable
names - it helped me to understand what was going on more quickly.
There's no need to put the Object Text in a string - this is
relatively slow and consumes memory that will not be freed until
DOORS exits. So, I put the Object Text in a buffer earlier in the
function, and search that. The 'if (!null bufObjText)' at my line 34
is equivalent to your 'objText1!=null'. If you prefer, 'if
(bufObjText != null)' does the same.
The conditional 'if (var_count ==0)' is redundant - I moved it's
functions into an earlier 'if' block (my line 40).
I moved the tests for deleted, table, row and cell objects up, so
that they occur before we take the time to fill a buffer with object
text - so that's only done if necessary.
Item 2 probably isn't going to have a performance impact, but the others will. The only quesiton is, how large?
Please let us know if this improves the running time over what you currently have. I don't have a sufficiently large set of sample data to make meaningful comparisons with your code.
Module modCurrent = current
Skip skUnused_Terminology_Data = create
Skip skSeeking_Terminology_Data = create()
put (skSeeking_Terminology_Data, 0, "SPONG")
put (skSeeking_Terminology_Data, 1, "DoD")
void Search_In_Entire_Module(Skip skTermsSought, skTermsNotFound)
{
Object obj
Buffer bufObjText = create()
int intSkipKey = 0
int index = 0
string strSkipData = ""
for strSkipData in skTermsSought do
{
int var_count = 0
bool blFoundTerm = false
for obj in modCurrent do
{
if (isDeleted obj){continue}
if (table obj) {continue}
if (row obj) {continue}
if (cell obj) {continue}
bufObjText = obj."Object Text"
if (!null bufObjText) then
{
Regexp re = regexp2 strSkipData
blFoundTerm = search (re, bufObjText, 0)
if ( blFoundTerm ) {
put(skUnused_Terminology_Data, intSkipKey, strSkipData)
intSkipKey++
}
bufObjText = ""
}
}
delete (bufObjText)
}
Search_In_Entire_Module (skSeeking_Terminology_Data, skUnused_Terminology_Data)
string strNotFound
for strNotFound in skUnused_Terminology_Data do
{
print strNotFound "\n"
}
delete skUnused_Terminology_Data
delete skSeeking_Terminology_Data
While I try to create a for in loop, it gives me an error stating "cant form Range with end < start". Value of i comes 4362626962. How can I fix it?
for i in 1...slashList.count{
let index = slashList[i]
if !quotaList.contains(index+1)
{
slashList.removeAtIndex(index)
}
}
Thank you in advance!
Your for has two problems:
If slashList.count is 0 (because slashList is empty), it would try to count from 1 to 0 adding 1 (which results in an infinite loop), that's why the compiler gives you the error start > end.
if slashList.count is greater than 0 (slashList is not empty), it would use an index which is out of bounds, because you count from 1 to slashList.count, while the indexes go from 0 to slashList.count - 1
to check all indexes it should be:
for i in 0 ..< slashList.count {
// your code
}
to ignore the first element (index 0) do:
for i in 1 ..< slashList.count {
// your code
}
for your special case, it would seem better to me to do something like:
for element in slashList {
if !quotaList.contains(element+1)
{
slashList.removeObject(element)
}
}
You can use removeObject from this answer. If, for some reason, you also need the index, do:
for (index, element) in slashList.enumerate() {
// your code
}
Try with, it should be 0.. not 1...
for i in 0..slashList.count{
let index = slashList[i]
if !quotaList.contains(index)
{
slashList.removeAtIndex(index)
}
}
Why you start loop from index 1 instead 0? If you really need this, you must check if slashList empty array:
if !slashList.isEmpty {
// your code here
}
Also removing items from array you numerating is bad practice. Assume that you want to loop from 0, then there is swifty way to get what you want:
slashList = slashList.enumerate().flatMap{quotaList.contains($0.index + 1) ? $0.element : nil}
I am new to programming and trying to find a simpler way to do this:
if state[0] != 0 && state[1] != 0 && state[2] != 0 && state[3] != 0 && state[4] != 0 && state[5] != 0 && state[6] != 0 && state[7] != 0 && state[8] != 0 {
gameOverLabel.text = "It's a tie."
gameOverLabel.hidden = false
active = false
}
I tried the code below but it reacted like a OR rather than a AND.
if state[0&1&2&3&4&5&6&7&8] != 0 {
gameOverLabel.text = "It's a tie."
gameOverLabel.hidden = false
active = false
}
Thanks for any help!
Assuming that your intention is to check if all array elements
are different from zero, the easiest approach would be
if !state.contains(0) { ... }
Your code
if state[0&1&2&3&4&5&6&7&8] != 0 { ... }
does not work
as intended because here the bitwise AND 0&1&2&3&4&5&6&7&8
is computed first (with result zero), so that is equivalent to
if state[0] != 0 { ... }
let state = [0,1,2,0,4,5,6,7]
if state.filter{$0 != 0}.count > 0 {
gameOverLabel.text = "It's a tie."
gameOverLabel.hidden = false
active = false
}
Try this one
The general case with an Array of indices
The short version
let indices = [4,2,9,6,5,3,8,0]
if !indices.contains({ state[$0] == 0 }) {
// ...
}
A second version which only shows the possibilities of Swift:
if !indices.lazy.map{ state[$0] }.contains(0) {
// ...
}
The lazy is used since otherwise map would apply the closure to all indices whereas lazy applies it on average only to half the elements (contains determines the number of executions of the closure).
Note: There is probably no performance improvement for a small amount of indices. The first version is certainly (ever so slightly) faster.
A specific range of indices
Just use the approach above with
let indices = 5...9
Or directly operate on the sub sequence of Array which is ArraySlice.
Side note: Even though it seems that ArraySlice (return type of Array[Range<Int>]) is a value type, internally it is a reference type (like Array) which only copies itself on mutation. In addition ArraySlice is only a view into the array (as long none of them is mutated). So it could be even faster than the first approach.
if !state[24...42].contains(0) {
// ...
}
I have a Swift n00b question.
I'm having a hard time understanding why I cannot remove an element from an array.
I first filter it twice to contain only the values I need:
let filteredShowtimes = movieShowtimes.filter{$0.dateTime.laterDate(newStartTime!).isEqualToDate($0.dateTime)}
var furtherFilteredShowtimes = filteredShowtimes.filter{$0.endTime.earlierDate(endTime!).isEqualToDate($0.endTime)}
And, down the line, inside a while loop that depends on the size of the array - but doesn't iterate over it or modify it - I try removing the first element like so:
furtherFilteredShowtimes.removeAtIndex(0)
But the element count remains the same.
Any idea what I'm missing?
Here's the whole code:
while(furtherFilteredShowtimes.count > 0) {
println("showtime \(furtherFilteredShowtimes.first!.dateTime)")
//if the start time of the movie is after the start of the time period, and its end before
//the requested end time
if (newStartTime!.compare(furtherFilteredShowtimes.first!.dateTime) == NSComparisonResult.OrderedAscending) && (endTime!.compare(furtherFilteredShowtimes.first!.endTime) == NSComparisonResult.OrderedDescending) {
let interval = 1200 as NSTimeInterval
//if the matching screenings dict already contains one movie,
//make sure the next one starts within 20 min of the previous
//one
if(theaterMovies.count > 1 && endTime!.timeIntervalSinceDate(newStartTime!) < interval {
//add movie to the matching screenings dictionary
println("we have a match with \(movies[currentMovie.row].title)")
theaterMovies[furtherFilteredShowtimes.first!.dateTime] = movies[currentMovie.row].title
//set the new start time for after the added movie ends
newStartTime = movieShowtimes.first!.endTime
//stop looking for screenings for this movie
break
}
else if(theaterMovies.count == 0) {
//add movie to the matching screenings dictionary
theaterMovies[furtherFilteredShowtimes.first!.dateTime] = movies[currentMovie.row].title
println("we have a new itinerary with \(movies[currentMovie.row].title)")
//set the new start time for after the added movie ends
newStartTime = furtherFilteredShowtimes.first!.endTime
//stop looking for screenings for this movie
break
}
}
else { //if the showtime doesn't fit, remove it from the list
println("removing showtime \(furtherFilteredShowtimes.first!.dateTime)")
furtherFilteredShowtimes.removeAtIndex(0)
}
}
You only say removeAtIndex(0) in one place, in an else.
So if it doesn't happen, that means that line is never being executed because the else is not executed - the if is executed instead.
And you break at the end of each if, so that's the end of the while loop!
In other words, let's pretend that the first two nested if conditions succeed. Your structure is like this:
while(furtherFilteredShowtimes.count > 0) {
if (something) {
if (somethingelse) {
break
break means jump out of the while, so if those two if conditions succeed, that's the end! We never loop. We certainly will never get to the removeAtIndex().
I'm getting confused with this and I know there will be a more slick way of starting it off. The 'result' variable has many records and I want to check if IN_SiteId is > 0 and filter on it, same after that for LandownerId and PaymentCategoryId etc. If I can get the right approach for the first 2 I will be ok from there. This should be easier but having a brick wall day. Any comments appreciated
public IQueryable rptRentPaidMonthly(int IN_SiteId, int IN_LandownerId, int IN_PaymentCategoryId, int IN_PaymentTypeId, string IN_ShowRelevantProportion)
{
var result = this._lmsDb.rptRentPaidMonthly(IN_daysFrom, IN_daysTo, IN_SiteId, IN_LandownerId, IN_PaymentCategoryId, IN_PaymentTypeId, IN_ShowRelevantProportion);
if (IN_SiteId > 0)
{
var searchResults = (from s in result
where (s.SiteId == #IN_SiteId)
select s);
return searchResults.AsQueryable();
}
return result.AsQueryable();
}
I'm not a LINQ expert but I think you can do something like this:
public IQueryable rptRentPaidMonthly(int IN_SiteId, int IN_LandownerId, int IN_PaymentCategoryId, int IN_PaymentTypeId, string IN_ShowRelevantProportion)
{
var result = this._lmsDb.rptRentPaidMonthly(IN_daysFrom, IN_daysTo, IN_SiteId, IN_LandownerId, IN_PaymentCategoryId, IN_PaymentTypeId, IN_ShowRelevantProportion);
var searchResults = (from s in result
where (IN_SiteId <= 0 || s.SiteId == IN_SiteId)
&& (IN_LandownerId <= 0 || s.LandownerId == IN_LandownerId)
&& (IN_PaymentCategoryId <= 0 || s.PaymentCategoryId == IN_PaymentCategoryId)
&& (IN_PaymentTypeId <= 0 || s.PaymentTypeId == In_PaymentTypeId)
select s);
return searchResults.AsQueryable();
}
The where clause checks if each filter value is less than or equal to 0, if so then it will return true and will not evaluate the next bit which attempts to filter the actual field on the value provided.