44from itertools import ifilterfalse
55import re
66import functools
7+ import random
78from sets import Set
89from threading import Timer
910
@@ -314,6 +315,34 @@ def pluck(self, key):
314315 """
315316 return self ._wrap ([x .get (key ) for x in self .obj ])
316317
318+ def where (self , attrs = None , first = False ):
319+ """
320+ Convenience version of a common use case of `filter`: selecting only objects
321+ containing specific `key:value` pairs.
322+ """
323+ if attrs is None :
324+ return None if first is True else []
325+
326+ method = _ .find if first else _ .filter
327+
328+ def by (val , * args ):
329+ for key , value in attrs .items ():
330+ try :
331+ if attrs [key ] != val [key ]:
332+ return False
333+ except KeyError :
334+ return False
335+ return True
336+
337+ return self ._wrap (method (self .obj , by ))
338+
339+ def findWhere (self , attrs = None ):
340+ """
341+ Convenience version of a common use case of `find`: getting the first object
342+ containing specific `key:value` pairs.
343+ """
344+ return self ._wrap (self ._clean .where (attrs , True ))
345+
317346 def max (self ):
318347 """ Return the maximum element or (element-based computation).
319348 """
@@ -335,7 +364,7 @@ def shuffle(self):
335364 return self ._wrap (list ())
336365
337366 cloned = self .obj [:]
338- import random
367+
339368 random .shuffle (cloned )
340369 return self ._wrap (cloned )
341370
@@ -369,6 +398,8 @@ def e(value, index, *args):
369398
370399 _ .each (obj , e )
371400
401+ if len (ns .result ) == 1 :
402+ return ns .result [0 ]
372403 return ns .result
373404
374405 def groupBy (self , val ):
@@ -386,6 +417,21 @@ def by(result, key, value):
386417
387418 return self ._wrap (res )
388419
420+ def indexBy (self , val = None ):
421+ """
422+ Indexes the object's values by a criterion, similar to `groupBy`, but for
423+ when you know that your index values will be unique.
424+ """
425+ if val is None :
426+ val = lambda * args : args [0 ]
427+
428+ def by (result , key , value ):
429+ result [key ] = value
430+
431+ res = self ._group (self .obj , val , by )
432+
433+ return self ._wrap (res )
434+
389435 def countBy (self , val ):
390436 """
391437 Counts instances of an object that group by a certain criterion. Pass
@@ -676,6 +722,17 @@ def bind(self, context):
676722 return self ._wrap (self .obj )
677723 curry = bind
678724
725+ def partial (self , * args ):
726+ """
727+ Partially apply a function by creating a version that has had some of its
728+ arguments pre-filled, without changing its dynamic `this` context.
729+ """
730+ def part (* args2 ):
731+ args3 = args + args2
732+ return self .obj (* args3 )
733+
734+ return self ._wrap (part )
735+
679736 def bindAll (self , * args ):
680737 """
681738 Bind all of an object's methods to that object.
@@ -863,6 +920,26 @@ def values(self):
863920 """
864921 return self ._wrap (self .obj .values ())
865922
923+ def pairs (self ):
924+ """ Convert an object into a list of `[key, value]` pairs.
925+ """
926+ keys = self ._clean .keys ()
927+ pairs = []
928+ for key in keys :
929+ pairs .append ([key , self .obj [key ]])
930+
931+ return self ._wrap (pairs )
932+
933+ def invert (self ):
934+ """ Invert the keys and values of an object. The values must be serializable.
935+ """
936+ keys = self ._clean .keys ()
937+ inverted = {}
938+ for key in keys :
939+ inverted [self .obj [key ]] = key
940+
941+ return self ._wrap (inverted )
942+
866943 def functions (self ):
867944 """ Return a sorted list of the function names available on the object.
868945 """
@@ -1176,6 +1253,15 @@ def times(self, func, *args):
11761253
11771254 return self ._wrap (func )
11781255
1256+ def random (self , max_number = None ):
1257+ """ Return a random integer between min and max (inclusive).
1258+ """
1259+ min_number = self .obj
1260+ if max_number is None :
1261+ min_number = 0
1262+ max_number = self .obj
1263+ return random .randrange (min_number , max_number )
1264+
11791265 def result (self , property , * args ):
11801266 """
11811267 If the value of the named property is a function then invoke it;
0 commit comments