Doctrine2 custom records order - doctrine-orm

I have simple query to get all pictures from database:
$this->createQueryBuilder('p')
->getQuery()
->getResult();
And I have array of ID's, which represents how they should be arranged in result array. How can I tell doctrine, to return these pictures in that specific order? For example, my "order array" is [3, 5, 9, 1, 10] and I want to get results in that particular order.

There are several ways to do this. If you're using postgresql you can try one of the raw queries here: ORDER BY the IN value list . If you're using mysql you can try the suggestions here: Ordering by the order of values in a SQL IN() clause
If you instead want to do it through straight Doctrine you could create a generic mapper function that orders the results. For very large result sets you may hit performance issues since you have O(n^2). But it's a little simpler than trying to make your own custom Doctrine function to handle it, relying on database implementation.
Say your query returns 5 results with the following ids: (95, 4, 1, 33, 35). Now say you want them returned as (1, 35, 4, 33, 95):
$entities = $em->getRepository('YourBundle:Picture')->findBy(/*some criteria*/);
$orderFunction = function($id) use ($entities)
{
foreach ($entities as $entity)
{
if ($entity->getId() == $id) {
return $entity;
}
}
};
$orderAs = array(1, 35, 4, 33, 95);
$orderedEntities = array_map($orderFunction, $orderAs);
Now your $orderedEntities array will be in the order you specified.

Related

Django bulk updating via F

I am trying to bulk update a number of objects for a given model. I figured I could do this via a dictionary together with F doing something like
FooBar.objects.filter(...).update(order = order_dict[F('id')])
where order_dict is something like
{1: 2, 2: 3, 3: 1, 4: 4}
objects with id equal to 1, 2, 3, and 4 exist but it is giving me a key error: F(id) nonetheless. Why precisely does this not work? And is there some way to achieve this other than updating objects one by one or using a 3th party package?

Creating an iterator to brute force

Hi so I am trying to write a function hack() that takes no arguments and returns an iterator over all possible passwords.
Basically, I have to user an iterator to brute force a password. All I know from the question is that:
The password consists of three segments.
The first segment of the password is a concatenation of two words in the following list of words: ["hello", "BEGONE", "dog", "MrCool"]
The middle segment is "Donkey20"
And the last segment consists of two digits that together (i.e. 1 and 7 = 17), are no larger than 38. (And at least 0)
My method of thinking is this:
Find all the possible combinations of POSSIBLE_WORDS by using permutations(). (Find all segment 1 possibilities)
For each combination in the new list, add "Donkey20" to the end. (For example: helloBEGONEDonkey20)
Find all possible combinations between the elements in THAT list and POSSIBLE_NUMBERS.
Create an iterator that iterates over all these possible passwords, and return it
My current code only is able to do step 2, but instead of Donkey20 being at the end of each combination it's at the start. (e.g. Donkey20helloBEGONE instead of helloBEGONEDonkey20)
POSSIBLE_WORDS = ["hello", "BEGONE", "dog", "MrCool"]
MIDDLE = "Donkey20"
possible_numbers1 = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15]
possible_numbers2 = [16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28]
possible_numbers3 = [29, 30, 31, 32, 33, 34, 35, 36, 37, 38]
POSSIBLE_NUMBERS = possible_numbers1 + possible_numbers2 + possible_numbers3
from itertools import permutations, combinations
def hack():
first_words = [''.join(word) for word in permutations(POSSIBLE_WORDS, 2)]
first_words.append(MIDDLE)
first_half = [''.join(word) for word in permutations(first_words, 2)]
Any way to fix this issue? How do I finish the remainder of the steps? Is there a different approach I could use to code this program?
Any help would be very much appreciated!
First of all, there is no reason to build up POSSIBLE_NUMBERS like that. Just use range(39) or list(range(39)) instead.
Your intention in
first_words.append(MIDDLE)
was almost certainly not to tack the single word "Donkey20" onto the end of the list of all possible first parts but was instead to tack it onto the end of each first word. I think that your intention in that part of the code can be better expressed by getting rid of that line as well as the following line and just use the single line
first_half = [word + MIDDLE for word in first_words]
When you are putting together the final possible passwords, you are going to need to turn the numbers into strings. Doubtless you already know about str() but that function has the drawback that str(1) is '1' whereas you probably want '01'. In this context, you might want to use format() since format(1,'02') returns '01'.
This should be enough of a hint to get you going. Since this seems to be homework I don't want to say any more.

np.delete and np.s_. What's so special about np_s?

I don't really understand why regular indexing can't be used for np.delete. What makes np.s_ so special?
For example with this code, used to delete the some of the rows of this array..
inlet_names = np.delete(inlet_names, np.s_[1:9], axis = 0)
Why can't I simply use regular indexing and do..
inlet_names = np.delete(inlet_names, [1:9], axis = 0)
or
inlet_names = np.delete(inlet_names, inlet_names[1:9], axis = 0)
From what I can gather, np.s_ is the same as np.index_exp except it doesn't return a tuple, but both can be used anywhere in Python code.
Then when I look into the np.delete function, it indicates that you can use something like [1,2,3] to delete those specific indexes along the entire array. So whats preventing me from using something similar to delete certain rows or columns from the array?
I'm simply assuming that this type of indexing is read as something else in np.delete so you need to use np.s_ in order to specify, but I can't get to the bottom of what exactly it would be reading it as because when I try the second piece of code it simply returns "invalid syntax". Which is weird because this code works...
inlet_names = np.delete(inlet_names, [1,2,3,4,5,6,7,8,9], axis = 0)
So I guess the answer could possibly be that np.delete only accepts a list of the indexes that you would like to delete. And that np._s returns a list of the indexes that you specify for the slice.
Just could use some clarification and some corrections on anything I just said about the functions that may be wrong, because a lot of this is just my take, the documents don't exactly explain everything that I was trying to understand. I think I'm just overthinking this, but I would like to actually understand it, if someone could explain it.
np.delete is not doing anything unique or special. It just returns a copy of the original array with some items missing. Most of the code just interprets the inputs in preparation to make this copy.
What you are asking about is the obj parameter
obj : slice, int or array of ints
In simple terms, np.s_ lets you supply a slice using the familiar : syntax. The x:y notation cannot be used as a function parameter.
Let's try your alternatives (you allude to these in results and errors, but they are buried in the text):
In [213]: x=np.arange(10)*2 # some distinctive values
In [214]: np.delete(x, np.s_[3:6])
Out[214]: array([ 0, 2, 4, 12, 14, 16, 18])
So delete with s_ removes a range of values, namely 6 8 10, the 3rd through 5th ones.
In [215]: np.delete(x, [3:6])
File "<ipython-input-215-0a5bf5cc05ba>", line 1
np.delete(x, [3:6])
^
SyntaxError: invalid syntax
Why the error? Because [3:4] is an indexing expression. np.delete is a function. Even s_[[3:4]] has problems. np.delete(x, 3:6) is also bad, because Python only accepts the : syntax in an indexing context, where it automatically translates it into a slice object. Note that is is a syntax error, something that the interpreter catches before doing any calculations or function calls.
In [216]: np.delete(x, slice(3,6))
Out[216]: array([ 0, 2, 4, 12, 14, 16, 18])
A slice works instead of s_; in fact that is what s_ produces
In [233]: np.delete(x, [3,4,5])
Out[233]: array([ 0, 2, 4, 12, 14, 16, 18])
A list also works, though it works in different way (see below).
In [217]: np.delete(x, x[3:6])
Out[217]: array([ 0, 2, 4, 6, 8, 10, 14, 18])
This works, but produces are different result, because x[3:6] is not the same as range(3,6). Also the np.delete does not work like the list delete. It deletes by index, not by matching value.
np.index_exp fails for the same reason that np.delete(x, (slice(3,6),)) does. 1, [1], (1,) are all valid and remove one item. Even '1', the string, works. delete parses this argument, and at this level, expects something that can be turned into an integer. obj.astype(intp). (slice(None),) is not a slice, it is a 1 item tuple. So it's handled in a different spot in the delete code. This is TypeError produced by something that delete calls, very different from the SyntaxError. In theory delete could extract the slice from the tuple and proceed as in the s_ case, but the developers did not choose to consider this variation.
A quick study of the code shows that np.delete uses 2 distinct copying methods - by slice and by boolean mask. If the obj is a slice, as in our example, it does (for 1d array):
out = np.empty(7)
out[0:3] = x[0:3]
out[3:7] = x[6:10]
But with [3,4,5] (instead of the slice) it does:
keep = np.ones((10,), dtype=bool)
keep[[3,4,5]] = False
return x[keep]
Same result, but with a different construction method. x[np.array([1,1,1,0,0,0,1,1,1,1],bool)] does the same thing.
In fact boolean indexing or masking like this is more common than np.delete, and generally just as powerful.
From the lib/index_tricks.py source file:
index_exp = IndexExpression(maketuple=True)
s_ = IndexExpression(maketuple=False)
They are slighly different versions of the same thing. And both are just convenience functions.
In [196]: np.s_[1:4]
Out[196]: slice(1, 4, None)
In [197]: np.index_exp[1:4]
Out[197]: (slice(1, 4, None),)
In [198]: np.s_[1:4, 5:10]
Out[198]: (slice(1, 4, None), slice(5, 10, None))
In [199]: np.index_exp[1:4, 5:10]
Out[199]: (slice(1, 4, None), slice(5, 10, None))
The maketuple business applies only when there is a single item, a slice or index.

Need a MongoDB query explanation

this is my first question on stackoverflow so be tolerant with a french rookie ;)
I have to simplify a MongoDB query and I've discovered this tool this morning on docs.mongodb.org and I really need to understand the methodology to continue to learn by myself.
Here is the query :
{$and: [{x: 2}, {y: 3}, {$and: [{z: 4}]}, {$or: [{name:{$regex: "toto."}}, {name:{$regex: "toto."}}]}]}
Thanks
Basically in SQL it is:
x = 3 AND y = 3 AND z = 4 AND (name LIKE 'toto%' OR name LIKE 'toto%')
This query can be massively simplified and I am not sure what tool you used to get this query, however, it can be brought down to:
{x: 2, y: 3, z: 4, name: {$in: [/^toto.*/, /^toto.*/]}}
This is since the default operator between query parts is actually $and so you only need $and in very specific cases, i.e. when you need to separately $and two clauses in a field or need to $and two separate $ors that, logically cannot be put together (for some reason).
I should note that in some drivers you need to replace the $in with an $or it depends on the constructs within the driver however, BSON regex objects (not the $regex operator) should be able to function within $in clauses etc.

Groovy: Iterate and multiply

I want to multiply every item in a list. But this example just returns every item:
list = 1..10
println list.each{it*2}
Use collect().
i.e.
list = 1..10
println list.collect{it*2}
Gives
[2, 4, 6, 8, 10, 12, 14, 16, 18, 20]
Only the syntax of Groovy is pegged to be standardized, not the default methods, so different implementations of Groovy have different names for the specific method to use.
In Codehaus Groovy (v 2.1.9 at groovy.codehaus.org) use collect...
list = 1..10
println list.collect{it*2}
In Real Groovy (v 0.10.0 at realgroovy.codeplex.com) use the more standardly named map...
test{
is [1,2,3,].map{it*7} == [7,14,21]
}
I'm not sure how GrooScript (at www.grooscript.org) does it.