How do I use itertools.groupby()?




I haven't been able to find an understandable explanation of how to actually use Python's `itertools.groupby()` function. What I'm trying to do is this:


* Take a list - in this case, the children of an objectified `lxml` element
* Divide it into groups based on some criteria
* Then later iterate over each of these groups separately.


I've reviewed [the documentation](https://docs.python.org/3/library/itertools.html#itertools.groupby), but I've had trouble trying to apply them beyond a simple list of numbers.


So, how do I use of `itertools.groupby()`? Is there another technique I should be using? Pointers to good "prerequisite" reading would also be appreciated.
**IMPORTANT NOTE:** You have to **sort your data** first.







The part I didn't get is that in the example construction



```
groups = []
uniquekeys = []
for k, g in groupby(data, keyfunc):
   groups.append(list(g))    # Store group iterator as a list
   uniquekeys.append(k)

```

`k` is the current grouping key, and `g` is an iterator that you can use to iterate over the group defined by that grouping key. In other words, the `groupby` iterator itself returns iterators.


Here's an example of that, using clearer variable names:



```
from itertools import groupby

things = [("animal", "bear"), ("animal", "duck"), ("plant", "cactus"), ("vehicle", "speed boat"), ("vehicle", "school bus")]

for key, group in groupby(things, lambda x: x[0]):
    for thing in group:
        print("A %s is a %s." % (thing[1], key))
    print("")
    

```

This will give you the output:



> 
> A bear is a animal.  
> 
> A duck is a animal.
> 
> 
> A cactus is a plant.
> 
> 
> A speed boat is a vehicle.  
> 
> A school bus is a vehicle.
> 
> 
> 


In this example, `things` is a list of tuples where the first item in each tuple is the group the second item belongs to.


The `groupby()` function takes two arguments: (1) the data to group and (2) the function to group it with.


Here, `lambda x: x[0]` tells `groupby()` to use the first item in each tuple as the grouping key.


In the above `for` statement, `groupby` returns three (key, group iterator) pairs - once for each unique key. You can use the returned iterator to iterate over each individual item in that group.


Here's a slightly different example with the same data, using a list comprehension:



```
for key, group in groupby(things, lambda x: x[0]):
    listOfThings = " and ".join([thing[1] for thing in group])
    print(key + "s:  " + listOfThings + ".")

```

This will give you the output:



> 
> animals: bear and duck.  
> 
> plants: cactus.  
> 
> vehicles: speed boat and school bus.
> 
> 
>
If your loading the items into array list then sort the array to group the items. 4th attempt! Now handles GroupItems. Feel free to ignore attempt 3, I've left it just for learning purposes. There are two ways you may want to handle groups: 1) calculate area for each individual item inside the group, or 2) calculate the aggregate area of all the grouped items. If you want option 2) just comment out the itemsInsideGroupItems line.

 

Just for fun I also changed the way the parameters work for specifying the target area value and unit. I put them in a string. Example values are: '4 square inches', '4in','4 sq inch' will give same result. Other examples are:'100mm', '800 pt'. If the parameter is a number, not a string, it will be interpreted as points.

 

 


```
// start with the selected items
var items = app.activeDocument.selection;

// comment out the following line if you want each groups' area to be calculated, rather than the items inside each group individually
items = itemsInsideGroupItems(items);

// this is where you specify your target size ()
scaleItemsToArea(items, '4 square inches');

function scaleItemsToArea(items, targetString) {
    // very simple parsing of targetString
    targetString = String (targetString);
    var targetAreaInSquareUnits = Number(targetString.match(/\d+/)[0]);
    var unitType;
    // note: only looks for 'in' or 'mm'
    if (targetString.search(/(in|\")/) > -1) {
        unitType = 'in';
    } else if (targetString.search(/mm/) > -1) {
        unitType = 'mm';
    } else {
        unitType = 'pt'
    }
    // scale each item
    for (var i = 0; i < items.length; i++) {
        scaleToArea(items[i], targetAreaInSquareUnits, unitType);
    }
}
function scaleToArea(item, targetAreaInSquareUnits, unitType) {
    var itemAreaInSquareUnits = areaOfItem(item, unitType);
    var scaleFactor = (Math.sqrt(targetAreaInSquareUnits / itemAreaInSquareUnits)) * 100;
    if (scaleFactor != NaN) {
        item.resize(scaleFactor, scaleFactor);
    }
}
function areaOfItem(item, unitType) {
    var itemAreaInSquareUnits;
    var itemAreaInSquarePoints = areaOfItemInSquarePoints(item);
    if (unitType == 'in') {
        var ptsIn1inch = 72;
        itemAreaInSquareUnits = itemAreaInSquarePoints / (ptsIn1inch * ptsIn1inch);
    } else if (unitType == 'mm') {
        var ptsIn1mm = 2.834645669;
        itemAreaInSquareUnits = itemAreaInSquarePoints / (ptsIn1mm * ptsIn1mm);
    } else {
        // no unitType specified, use points
        itemAreaInSquareUnits = itemAreaInSquarePoints;
    }
    return itemAreaInSquareUnits;
}
function areaOfItemInSquarePoints(item) {
    var area = 0;
    if (item.typename == 'PathItem') {
        area = item.area;
    } else if (item.typename == 'CompoundPathItem') {
        for (var j = 0; j < item.pathItems.length; j++) {
            area += item.pathItems[j].area;
            // $.writeln('item.pathItems[j].area = ' + item.pathItems[j].area + '     area = ' + area);
        }
    } else if (item.typename == 'GroupItem') {
        for (var j = 0; j < item.pageItems.length; j++) {
            area += areaOfItemInSquarePoints(item.pageItems[j]);
            // $.writeln('item.pathItems[j].area = ' + item.pathItems[j].area + '     area = ' + area);
        }
    } else {
        // for other types of items, resort to width x height
        area = item.width * item.height;
    }
    return Math.abs(Math.round(area * 10000) / 10000);
}
function itemsInsideGroupItems(items) {
    // returns an array containing items, including items found inside GroupItems
    try {
        var found = [];
        for (var i = 0; i < items.length; i++) {
            var item = items[i];
            if (item.typename == 'GroupItem') {
                found = found.concat(itemsInsideGroupItems(item.pageItems));
            } else {
                found.push(item);
            }
        }
        return found;
    } catch (e) {
        return found;
    }
}
```
 

 

As usual, not much testing done, so please let me know if it works as you'd expect. - Mark g = findgroups(yourtable.name);
output = splitapply(@(varargin) {table(varargin{:}, 'variablenames', yourtable.properties.variablenames)}, yourtable, g);
this should give a cell array of tables. Using [reflection](/questions/tagged/reflection "show questions tagged 'reflection'") and [expression-trees](/questions/tagged/expression-trees "show questions tagged 'expression-trees'") you can provide the parameters and then call `OrderBy` function, Instead of returning `Expression<Func<Task, T>>` and then calling `OrderBy`.


Note that `OrderBy` is an extension method and has implemented in both `System.Linq.Enumarable` and `System.Linq.Queryable` classes. The first one is for [linq-to-objects](/questions/tagged/linq-to-objects "show questions tagged 'linq-to-objects'") and the latter is for [linq-to-entities](/questions/tagged/linq-to-entities "show questions tagged 'linq-to-entities'"). [entity-framework](/questions/tagged/entity-framework "show questions tagged 'entity-framework'") needs the expression tree of the query in order to translate it to SQL commands. So we use the `Queryable` implementation.


It can be done by an extension method(explanations added as comments):



```
public static IOrderedQueryable<TSource> OrderBy<TSource>(
       this IQueryable<TSource> query, string propertyName)
{
    var entityType = typeof(TSource);

    //Create x=>x.PropName
    var propertyInfo = entityType.GetProperty(propertyName);
    ParameterExpression arg = Expression.Parameter(entityType, "x");
    MemberExpression property = Expression.Property(arg, propertyName);
    var selector = Expression.Lambda(property, new ParameterExpression[] { arg });

    //Get System.Linq.Queryable.OrderBy() method.
    var enumarableType = typeof(System.Linq.Queryable);
    var method = enumarableType.GetMethods()
         .Where(m => m.Name == "OrderBy" && m.IsGenericMethodDefinition)
         .Where(m =>
         {
            var parameters = m.GetParameters().ToList();
            //Put more restriction here to ensure selecting the right overload                
            return parameters.Count == 2;//overload that has 2 parameters
         }).Single();
    //The linq's OrderBy<TSource, TKey> has two generic types, which provided here
    MethodInfo genericMethod = method
         .MakeGenericMethod(entityType, propertyInfo.PropertyType);

    /*Call query.OrderBy(selector), with query and selector: x=> x.PropName
      Note that we pass the selector as Expression to the method and we don't compile it.
      By doing so EF can extract "order by" columns and generate SQL for it.*/
    var newQuery = (IOrderedQueryable<TSource>)genericMethod
         .Invoke(genericMethod, new object[] { query, selector });
    return newQuery;
}

```

Now you can call this overload of `OrderBy` like any other overload of it.  

For example:



```
var cheapestItems = _context.Items.OrderBy("Money").Take(10).ToList();

```

Which translates to:



```
SELECT TOP (10)  {coulmn names} FROM  [dbo].[Items] AS [Extent1] 
       ORDER BY [Extent1].[Money] ASC

```

This approach can be used to define all overloads of `OrderBy` and `OrderByDescending` methods to have `string` property selector. according to python idiomatic, its better to ask for forgiveness (except) then for permission (if). which would make your solution a better fit

however, i disagree with the slicing used in both solutions. you have the index, so its easy to update an element at an index:

the\_list[index] = 'new valu… if you want each cart item to to have each selected employee,

pass item to select\_emplyee(i) method not index for ex. (click)=“select\_emplyee(item)”.

then in implementation add one more extended property to your cartlist json called employeename.

select\_emplyee(item) {



this.employee\_alert… i wouldn’t touch the python. add it into a custom node so you can make use of list levels and lacing instead. th is will also make it easier to maintain your code over time. Here is a sample of traversing a simple xml structure

 
```
    Dim myxml = <root>
                    <level id="1">
                        <prop n="PROPERTY" v="VALUE"/>
                    </level>
                    <level id="2">
                        <prop n="PROPERTY" v="VALUE"/>
                    </level>
                </root>

    For Each level In myxml.Elements
        Debug.WriteLine("id=" & level.@id.ToString)
        For Each prop In level.Elements
            Debug.WriteLine("n=" & prop.@n.ToString & "  v=" & prop.@v.ToString)
        Next
    Next

``` your link leads to an inactive developer message btw.

rest does not yet provide a way to list tags except by id. you can use the standard api with the same oauth2 access key that you would use for rest… using the data object you would want to query on the group table using the groupname field. as long as you write down the hierarchy manually, there’s certainly the possibility to simplify such transitive from implementations with a macro. [i’ve written one here, feel free to take a look.](https://play.rust-lang.org/?version=stable&mode=debug&edition=2018&gist=337cce675aa28e99ac030ca783c1c155) going even further one could try to use procedural macros with global state that uses annotations on the…