Sort response.products before saving into NSArray so I get fixed index every time - nsarray

I went through Ray's in app purchase tutorial at
I got it working, but I found that the product response from Apple uses NSSet, and so the order is changed each time.
I'm hoping to sort it alphabetically before saving it into an array I can use later.
- (void)productsRequest:(SKProductsRequest *)request didReceiveResponse:(SKProductsResponse *)response {
NSLog(#"Received products results...");
self.products = response.products;
self.request = nil;
[[NSNotificationCenter defaultCenter] postNotificationName:kProductsLoadedNotification object:_products];
}
I'd like to get response.products and sort it before saving it into self.products, that way the index number will be predictable.
Any tips?
Thanks.

Related

Ordering dictionary in context Django

I looked at this thread, with an example of sorting dictionaries.
I have a dictionary of programme objects where the key is a programme object and the value is a lookup of the number of related Project objects.
def DepartmentDetail(request, pk):
department = Department.objects.get(pk=pk)
programmes = Programme.objects.all().filter(department=department).exclude(active=False).order_by('long_name')
combi = {}
for p in programmes:
prj = Project.objects.all().filter(programme=p)
combi[p] = str(len(prj))
return render(request, 'sysadmin/department.html',{'department': department, 'programmes': programmes, 'combi': sorted(combi.items())})
In the model, Programme returns a string 'long_name', so I believe that I am trying to sort a string key and a string value.
In the template I get to the keys and values as so,
{% for programme, n in combi %}
This gives me the error..
unorderable types: Programme() < Programme()
I don't really understand the error, in the python 3 documentation it states that the sorted() method accepts any iterable - So why does this happen?
I'm looking at collections.OrderedDict to solve the problem, but I want to know why this doesn't work.
Thanx.
Databases with index on columns are really good at sorting. There's almost never a need to sort on the client side. You can almost always do it in the server. The funny part it you apparently know how to do it too.
....exclude(active=False).order_by('long_name') # <--- this
Guess what, your data is already sorted there isn't a need to sort it again inside python!!
But there is a much bigger issue in your code. You are fetching a set of Project items and then looping through that set to retrieve them all over again one by one. So if you have 200 Project items you are doing 200 queries when one query does the job just as well. Just add select_related or prefetch_related depending on which direction you have the relationship.
Your code ideally should be something like this
department = Department.objects.get(pk=pk)
programmes = Programme.objects.all().filter(department=department).exclude(active=False).order_by('long_name')
return render(request, 'sysadmin/department.html',{'department': department, 'programmes': programmes,})
As far as I can see combi just contains duplicated data. The same thing can be accessed from programmes eg. programme.project_set.all()
(again this depends on which direction you have the relationship, your models are not shown)
Recommended reading: https://docs.djangoproject.com/en/1.10/ref/models/fields/#django.db.models.ForeignKey
The issue is that sorted expects a way to be able to order the items and by default there isn't any way to know how to order your objects. You can provide a key
sorted(combi.items(), key=lambda i: i.long_name)

RealmSwift limiting and fetching last 30 records into tableview

I'm a newbie of using RealmSwift and i'm creating chat like application using swift 3.0 with backend database as RealmSwift. while inserting the chat works good into realm, but the thing when fetch the records
let newChat = uiRealm.objects(Chats.self).filter(
"(from_id == \(signUser!.user_id)
OR from_id == \(selectedList.user_id))
AND (to_id == \(signUser!.user_id)
OR to_id == \(selectedList.user_id))"
).sorted(byProperty: "id", ascending: true)
i don't know how to limit the last 30 records for the chat conversation. In the above code i just fetch the records from "Chat" table with filtering the chat as "SIGNED USERID AND TO USERID". and also if i list all the records(like more than 150 chat conversation) for the particular chat, then scrolling up the records from tableview got stuck up or hang for a while. So please give some idea about how to limit last 30 records and stop hanging the tableview. Thanks in advance
Like I wrote in the Realm documentation, because Realm Results objects are lazily-loaded, it doesn't matter if you query for all of the objects and then simply load the ones you need.
If you want to line it up to a table view, you could create an auxiliary method that maps the last 30 results to a 0-30 index range, which would be easier to then pass straight to the table view's data source:
func chat(atIndex index: Integer) -> Chats {
let mappedIndex = (newChat.count - 30) + index
return newChat[mappedIndex]
}
If you've already successfully queried and started accessing these objects (i.e. the query itself didn't hang), I'm not sure why the table view would hang after the fact. You could try running the Time Profiler in Instruments to track down exactly what's causing the main thread to be blocked.

How do I do math in a Django inclusion tag with a while loop to show a result based on a filter?

I'm trying to write a simple inclusion tag that will do the following:
Get all time recorded for a user ordered by project
Add together the time for all projects
Return an object list that sorts the projects by most time spent and
the total
The first item is easy.
#register.inclusion_tag('time/_total_time_per_project_ytd.html')
def show_total_time_by_project():
time = Time.objects.all().order_by('project')
return {'time': time}
I think something like this is what I need:
#register.inclusion_tag('time/_total_time_per_project_ytd.html')
def show_total_time_by_project():
time = Time.objects.all().order_by('project')
while time.project = project
# this is where I'm lost. How do I do the math?
return time_total
return {'time': time_total}
Then I loop through time and the result will be an object_list that has three records with three projects and the total time for each project. As you guessed, I'm a noob, so please use wet noodles. Thanks!

I'm confused about how distinct() works with Django queries

I have this query:
checkins = CheckinAct.objects.filter(time__range=[start, end], location=checkin.location)
Which works great for telling me how many checkins have happened in my date range for a specific location. But I want know how many checkins were done by unique users. So I tried this:
checkins = CheckinAct.objects.filter(time__range=[start, end], location=checkin.location).values('user').distinct()
But that doesn't work, I get back an empty Array. Any ideas why?
Here is my CheckinAct model:
class CheckinAct(models.Model):
user = models.ForeignKey(User)
location = models.ForeignKey(Location)
time = models.DateTimeField()
----Update------
So now I have updated my query to look like this:
checkins = CheckinAct.objects.values('user').\
filter(time__range=[start, end], location=checkin.location).\
annotate(dcount=Count('user'))
But I'm still getting multiple objects back that have the same user, like so:
[{'user': 15521L}, {'user': 15521L}, {'user': 15521L}, {'user': 15521L}, {'user': 15521L}]
---- Update 2------
Here is something else I tried, but I'm still getting lots of identical user objects back when I log the checkins object.
checkins = CheckinAct.objects.filter(
time__range=[start, end],
location=checkin.location,
).annotate(dcount=Count('user')).values('user', 'dcount')
logger.info("checkins!!! : " + str(checkins))
Logs the following:
checkins!!! : [{'user': 15521L}, {'user': 15521L}, {'user': 15521L}]
Notice how there are 3 instances of the same user object. Is this working correctly or not? Is there a difference way to read out what comes back in the dict object? I just need to know how many unique users check into that specific location during the time range.
The answer is actually right in the Django docs. Unfortunately, very little attention is drawn to the importance of the particular part you need; so it's understandably missed. (Read down a little to the part dealing with Items.)
For your use-case, the following should give you exactly what you want:
checkins = CheckinAct.objects.filter(time__range=[start,end], location=checkin.location).\
values('user').annotate(checkin_count=Count('pk')).order_by()
UPDATE
Based on your comment, I think the issue of what you wanted to achieve has been confused all along. What the query above gives you is a list of the number of times each user checked in at a location, without duplicate users in said list. It now seems what you really wanted was the number of unique users that checked in at one particular location. To get that, use the following (which is much simpler anyways):
User.objects.filter(checkinat__location=location).distinct().count()
UPDATE for non-rel support
checkin_users = [(c.user.pk, c.user) for c in CheckinAct.objects.filter(location=location)]
unique_checkins = len(dict(checkin_users))
This works off the principle that dicts have unique keys. So when you convert the list of tuples to a dict, you end up with a list of unique users. But, this will generate 1*N queries, where N is the total amount of checkins (one query each time the user attribute is used. Normally, I'd do something like .select_related('user'), but that too requires a JOIN, which is apparently out. JOINs not being supported seems like a huge downside to non-rel, if true, but if that's the case this is going to be your only option.
You don't want DISTINCT. You actually want Django to do something that will end up giving you a GROUP BY clause. You are also correct that your final solution is to combine annotate() and values(), as discussed in the Django documentation.
What you want to do to get your results is to use annotate first, and then values, such as:
CheckinAct.objects.filter(
time__range=[start, end],
location=checkin.location,
).annotate(dcount=Count('user').values('user', 'dcount')
The Django docs at the link I gave you above show a similarly constructed query (minus the filter aspect, which I added for your case in the proper location), and note that this will "now yield one unique result for each [checkin act]; however, only the [user] and the [dcount] annotation will be returned in the output data". (I edited the sentence to fit your case, but the principle is the same).
Hope that helps!
checkins = CheckinAct.objects.values('user').\
filter(time__range=[start, end], location=checkin.location).\
annotate(dcount=Count('user'))
If I am not mistaken, wouldn't the value you want be in the input as "dcount"? As a result, isn't that just being discarded when you decide to output the user value alone?
Can you tell me what happens when you try this?
checkins = CheckinAct.objects.values('user').\
filter(time__range=[start, end], location=checkin.location).\
annotate(Count('user')).order_by()
(The last order_by is to clear any built-in ordering that you may already have at the model level - not sure if you have anything like that, but doesn't hurt to ask...)

Sort list of items in Django

I have a Django view called change_priority. I'm posting a request to this view with a commas separated list of values which is basically the order of the items in my model. The data looks like this:
1,4,11,31,2,4,7
I have a model called Items which has two values - id and priority. Upon getting this post request, how can I set the priority of the Item depending upon the list order. So my data in the db would look like.
1,1
4,2
11,3
31,4
2,5
4,6
7,7
Thanks guys.
You don't really give much detail about how exactly you're receiving the information, but here's a stab at it.
order = data.split(',') # convert data string to a list
objects = MyModel.objects.in_bulk(order)
for i, id in enumerate(order):
obj = objects['id']
obj.priority = i
obj.save()