replaceObjectAtIndex problem

G’day

I can’t get the terminology right for ‘replaceObjectAtIndex’. When I add withObject_(y-1) it won’t compile.

Any suggestions please?

Regards

Santa


set x to 0
	repeat
		set theClientToFind to theClientList's objectAtIndex_(x)
		if tempClientString = theClientToFind as text then
			set y to theClientListNumberKeeper's objectAtIndex_(x)
			theClientListNumberKeeper's replaceObjectAtIndex_(x) withObject_(y+1) 
			exit repeat
		end if
		set x to x + 1
	end repeat

Hi,

as the method says, withObject must be an object. An index is no object.
For example

theClientListNumberKeeper's replaceObjectAtIndex_(x) withObject_(theClientList's objectAtIndex_(y+1)) 

G’day Stefan

theClientListNumberKeeper’s objectAtIndex_(x) stores a number.

I want to add 1 to it and put the value back in.

How do I do that please?

Regards

Santa

Edit

This won’t compile…

theClientListNumberKeeper's replaceObjectAtIndex_(x) withObject_(theClientListNumberKeeper's objectAtIndex_(x)+1)

you cannot do math with NSNumber objects.

Use NSDecimalNumber or cast the NSNumber object to a primitive, do the math and create a new NSNumber object from the result

Stefan, the line you’ve supplied won’t compile on my machine for love nor money.

I’ve rebooted to make sure nothing was wrong, but no good.

The first part will compile, but as soon as I uncomment the second part, it won’t save.

Any suggestions anyone please? (take it easy on me, i still don’t know what Stefan means in his last post, but I’m reading up on it.)


theClientListNumberKeeper's replaceObjectAtIndex_(x) --withObject_(theClientList's objectAtIndex_(y)) 
										

Regards

Santa

You’re not writing the function properly. The declaration goes all together (no spaces between underscores) and then the variables go together inside of parathesis

Like so:

theClientListNumberKeeper’s replaceObjectAtIndex_withObject_(x,(theClientList’s objectAtIndex_(y)))

Thanks Super, that compiled.

Now, if someone doesn’t mind, how the heck do I follow Stefans advice to

My code looks like this, but naturally the set y to y+1 part is crashing. I’ve googled, but examples aren’t around.

Regards

Santa


repeat with paragraphCycle in paragraphs of item 1 of tempWholeList -- run through the clients in .dat
					try
						set tempClientString to my SeparateOutClient(paragraphCycle) as text
						if tempClientString ≠ "" and tempClientString is not in {","} then
							--theClientListArray's addObjectsFromArray_({tempClientString}) --< Make VERY long list
							if tempClientString is not in items of theClientListTEMP then
								theClientList's addObjectsFromArray_({tempClientString}) --< Make short list of Clients
								theClientListNumberKeeper's addObjectsFromArray_({1}) --< Make short list of numbers
								set end of theClientListTEMP to tempClientString
							else
								set x to 0
								repeat
									set theClientToFind to theClientList's objectAtIndex_(x)
									if tempClientString = theClientToFind as text then
										set y to theClientListNumberKeeper's objectAtIndex_(x)
										set y to y + 1
										theClientListNumberKeeper's replaceObjectAtIndex_withObject_(x, (y))
										exit repeat
									end if
									set x to x + 1
								end repeat
							end if
						end if
					on error errmsg number errnum
						display dialog errmsg & " " & errnum
					end try
				end repeat

Googling this is hopeless.

From the ObjC stuff I’ve read, I need to use something like the following, but don’t know exactly what. Anyone please.


theClientListNumberKeeper's addObjectsFromArray_(numberWithInt_(1)) --< Make short list of numbers

try:

set y to theClientListNumberKeeper’s objectAtIndex_(x) as integer
set y to y+1
theClientListNumberKeeper’s replaceObjectAtIndex_withObject_(x, y)

The “as integer” coerces the NSNumber x to an AS integer (use “as real” if the number has decimals)

Ric

After Edit: I wanted to point out one more thing. When you’re adding one thing to an array, you should use addObject rather then addObjectsFromArray, so:

theClientList's addObjectsFromArray_({tempClientString}) 
theClientListNumberKeeper's addObjectsFromArray_({1}) 

should be:

theClientList's addObject_(tempClientString) 
  theClientListNumberKeeper's addObject_(1)  

I haven’t tested it but try this


repeat
    set theClientToFind to theClientList's objectAtIndex_(x)
    if tempClientString = theClientToFind as text then
   		set y to theClientListNumberKeeper's objectAtIndex_(x)'s as integer
   		set y to y + 1
   		set yObject to current application's NSNumber's numberWithUnsignedInt_(y)
   		theClientListNumberKeeper's replaceObjectAtIndex_withObject_(x, (yObject))
    	exit repeat
    end if
    set x to x + 1
end repeat

Stefan,

It’s not really necessary to do that in ASOC. You can pass AS numbers to cocoa methods without having to convert them explicitly to NSNumbers. I tested my code that I posted above, and if you add this line to the end: “log theClientListNumberKeeper’s objectAtIndex_(x)'s |class|()”, you get NSCFNumber.

Ric

Indeed, thanks

Also don’t use unsignedInt because applescript’s integers aren’t unsigned ints. They are more like double types because an unsignedInt has a value between 0 and 4294967295 (32 bit number) and signed ints (int) can have values from -2147483647 till 2147483647 (31 bit number + 1 bit for positive or negative number). Applescript’s range is much higher than this so you can have an error with this type. That’s why -2147483647 this is a famous number in error logs. This happens when the computers try to put a long or double value in an int. The system can’t handle it so the number will be the lowest possible number for int or 0 for unsigned ints. It’s safely to use NSNumber’s numberWithDouble_() but like rdelmar suggested this isn’t neccesary because this wil do the applescriptObjC framework for you so you don’t have to hard code it yourself.

Thank you very much gentlemen.

Now I just need to see if it’s possible to speed this bit of code up by writing it in ObjC.

Ric in my previous thread you said one of your routines sped up by a factor of 270; well this routine takes over 2000 seconds, which means it has the possibility of speeding up quite considerably.

What are my chances of getting it down a bit? I know the outer loop can’t be altered cause I’m calling a handler, but the ones that interest me are the adding to the arrays and replacing in the array.

I have trouble learning from documentation, but as soon as I see concrete examples I have no problems understanding them.

This bit in particular is VERY slow.


set x to 0
								repeat
									set theClientToFind to theClientList's objectAtIndex_(x)
									if tempClientString = theClientToFind as text then
										set y to theClientListNumberKeeper's objectAtIndex_(x) as integer
										set y to y + 1
										theClientListNumberKeeper's replaceObjectAtIndex_withObject_(x, y)
										exit repeat
									end if
									set x to x + 1
								end repeat

Regards

Santa



repeat with paragraphCycle in paragraphs of item 1 of tempWholeList -- run through the clients in .dat
					try
						set tempClientString to my SeparateOutClient(paragraphCycle) as text
						if tempClientString ≠ "" and tempClientString is not in {","} then
							--theClientListArray's addObjectsFromArray_({tempClientString}) --< Make VERY long list
							if tempClientString is not in items of theClientListTEMP then
								theClientList's addObject_({tempClientString}) --< Make short list of Clients
								theClientListNumberKeeper's addObject_(1) --< Make short list of numbers
								set end of theClientListTEMP to tempClientString
							else
								set x to 0
								repeat
									set theClientToFind to theClientList's objectAtIndex_(x)
									if tempClientString = theClientToFind as text then
										set y to theClientListNumberKeeper's objectAtIndex_(x) as integer
										set y to y + 1
										theClientListNumberKeeper's replaceObjectAtIndex_withObject_(x, y)
										exit repeat
									end if
									set x to x + 1
								end repeat
							end if
						end if
					on error errmsg number errnum
						display dialog errmsg & " " & errnum
					end try
				end repeat

You should consider my post in another question (another topic) I answered by using applescript’s way of speeding things up instead of using cocoa for this. if you prefer using cocoa objects then don’t bring your data back to applescript.

Because you’re using applescript’s integers I would say it’s faster to convert from an NSArray to a list once then all the converting you do now. What you’re doing is having a loop in cocoa objects, transfer it’s content to applescript classes and eventually posting it back into an cocoa object. Every loop there are multiple transformations of objects, so if it repeats hundreds of times I can image that it would take long.

The solution for your repeat is to stay in applescript or asoc but don’t mix things up. With asoc look into NSDecimalNumber (mutable subclass of NSNumber) to be able to change object value in your NSMutableArray. Then don’t use updateObject but access the object’s instance method in theArray directly to change it’s value to avoid the overhead you created now.

Thanks DJ

I’d like to try and get this working using arrays, then attempt (he says laughingly) to write it in ObjC.

According to Ric, I should be able to achieve far faster speed that way.

ATM I’m having problems with this routine, it constantly returns ‘false’. it’s copied from Leons suggestion in my other post.

Once I get this working, I’ll try and work out how NSDecimalNumber works.

Regards

Santa


set myStringToFind to tempClientString
tell current application's NSString to set stringToFind to stringWithString_(myStringToFind)
set theResult to theClientList's containsObject_(stringToFind)
if not theResult then
		theClientList's addObject_({tempClientString}) --< Make short list of Clients
		theClientListNumberKeeper's addObject_(1) --< Make short list of numbers

I’m not sure what you need help with now – In your last 2 posts, you’ve attached 3 different pieces of code. Do they all need fixing?

 theClientList's addObject_({tempClientString})

this should be: theClientList’s addObject_(tempClientString) with no curly brackets.

Ric

Well, the first bit was easy, just need to add ‘as string’ to Leons suggestion.

Thanks Ric, duly amended.

But I’m having real problems with the decimal number bit

Whats wrong with my second line here, please?


tell current application's NSString to set stringToFind to stringWithString_(tempClientString as string)
tell current application's NSNumber to set StartingNumber to decimalNumberWithDecimal_(1)

Ric, I’m trying to get a faster way to arrange my data then the other thread. I think that if I can get this to work as an ObjC piece of code, it will be much faster than going through a giant list of Clients.

I’m having to build up alist of Clients anyway, so why not just increment a ‘parallel’ array as I strike an existing Client.

Trouble is, going through the Clients in a loop in asoc is very slow, but i thought if i could work out how to do it with arrays, writing the ObjC would be much clearer.

ATM I’m having hassles getting DecimalNumber to work, and have no idea how to increment a stored decimal number by 1

It would be nice if I could get the offset of an instance of a particular Client in an array, but it seems i have to use a repeat loop for comparison.

Regards, and thanks for your interest.

Santa

I think (more like I hope) I’m getting the hang of this.

Thanks to Stefans remark about addressing objects in my other thread, I decided to try…


theClientListNumberKeeper's replaceObjectAtIndex_withObject_(x, ((theClientListNumberKeeper's objectAtIndex_(x) as integer) + 1))

and it works.

Now I need to know, is it feasible to convert any of the following to ObjC?

Regards, and thanks

Santa




repeat with paragraphCycle in paragraphs of item 1 of tempWholeList -- run through the clients in .dat
					try
						set tempClientString to my SeparateOutClient(paragraphCycle) as text
						if tempClientString ≠ "" and tempClientString is not in {","} then
							--set myStringToFind to tempClientString as string
							tell current application's NSString to set stringToFind to stringWithString_(tempClientString as string)
							--tell current application's NSNumber to set StartingNumber to decimalNumberWithDecimal_(1)
							set theResult to theClientList's containsObject_(stringToFind)
							if not theResult then
								theClientList's addObject_(tempClientString) --< Make short list of Clients
								theClientListNumberKeeper's addObject_(1) --< Make short list of numbers
							else
								set x to 0
								repeat
									set theClientToFind to theClientList's objectAtIndex_(x) as string
									if tempClientString = theClientToFind as text then
										theClientListNumberKeeper's replaceObjectAtIndex_withObject_(x, ((theClientListNumberKeeper's objectAtIndex_(x) as integer) + 1))
										exit repeat
									end if
									set x to x + 1
								end repeat
							end if
						end if
					on error errmsg number errnum
						display dialog errmsg & " " & errnum
					end try
				end repeat