How do you group elements in a List<P> to a Map<K, List<V>> while retaining order?

group similar elements in list python
python group elements in list by value
python group list by 3
python list group by count
python list(group by key)
how to group elements in a list
python3 list group by
python group list every nth element

I have a List of Google PlaceSummary objects taken from the Google Places API. I'd like to collect and group them by their Google Place ID, but also retain the order of the elements. What I thought would work would be:

Map<String, List<PlaceSummary>> placesGroupedByPlaceId =
            places.stream()
                  .collect(Collectors.groupingBy(
                          PlaceSummary::getPlaceId,
                          LinkedHashMap::new,
                          Collectors.mapping(PlaceSummary::getPlaceId, toList())
                  ));

But it won't even compile. It looks like it should according to the Java API documentation on Collectors.

Previously I had this code:

    Map<String, List<PlaceSummary>> placesGroupedByPlaceId = places.stream()
            .collect(Collectors.groupingBy(PlaceSummary::getPlaceId));

However standard .collect() on the Streams API does not retain the order of elements in the subsequent HashMap (obviously since HashMaps are unordered). I wish for the output to be a LinkedHashMap so that the Map is sorted by the insertion order of each bucket.

However, the solution I suggested doesn't compile. Firstly, it doesn't recognise the PlaceSummary::getPlaceId since it says it's not a function - even though I know it is. Secondly, it says I cannot convert LinkedHashMap<Object, Object> into M. M is supposed to be a generic collection, so it should be accepted.

How do I convert the List into a LinkedHashMap using the Java Stream API? Is there a succinct way to do it? If it's too difficult to understand I may just resort to old school pre-Java 8 methods.

I noticed that there is another Stack Overflow answer on converting List to LinkedHashMap, but this doesn't have a solution I want as I need to collect 'this' the object I'm specifically iterating over.

You're really close to what you want:

Map<String, List<PlaceSummary>> placesGroupedByPlaceId =
            places.stream()
                  .collect(Collectors.groupingBy(
                          PlaceSummary::getPlaceId,
                          LinkedHashMap::new,
                          Collectors.mapping(Function.identity(), Collectors.toList())
                  ));

In the Collectors.mapping method, you need to give the PlaceSummary instance and not the place ID. In the code above, I used Function.identity(): this collector is used to build the values so we need to accumulate the places themselves (and not their ID).

Note that it is possible to write directly Collectors.toList() instead of Collectors.mapping(Function.identity(), Collectors.toList()).

The code you have so far does not compile because it is in fact creating a Map<String, List<String>>: you are accumulating the IDs for each ID (which is quite weird).


You could write this as a generic method:

private static <K, V> Map<K, List<V>> groupByOrdered(List<V> list, Function<V, K> keyFunction) {
    return list.stream()
                .collect(Collectors.groupingBy(
                    keyFunction,
                    LinkedHashMap::new,
                    Collectors.toList()
                ));
}

and use it like this:

Map<String, List<PlaceSummary>> placesGroupedById = groupByOrdered(places, PlaceSummary::getPlaceId);

Grouping elements in a list of lists, You can use a dict for grouping. To make things easier defaultdict is a good sub-​class of dict for this case: from collections import defaultdict  A crude method may be, but here you go - l = [1,2,3,4,5,6,7,8] [ int(str(l[a])+str(l[a+1])) for a in range(0,len(l),2) ] 1. range(0,len(l),2) ] is iterating over every other element. l[a] and l[a+1] are getting converted to string, concatenated. The output is getting casted back to int. Finally the whole logic is done in a list comprehension in

I think you got a little confused about the final collector. It merely represents what needs to be in each map value. There is no need to have a secondary mapping collector, as you just want a list of the original objects.

    Map<String, List<PlaceSummary>> placesGroupedByPlaceId =
          places.stream()
                .collect(Collectors.groupingBy(PlaceSummary::getPlaceId,
                                               LinkedHashMap::new,
                                               Collectors.toList()));

python : group elements together in list, You can pair adjacent items by zipping the list with itself but with a padding of float('nan') since it can't be equal to any object, and then iterate  There are 118 elements on the periodic table. Each element is identified by the number of protons in its atoms. This number is the atomic number. The periodic table lists the elements in order of increasing atomic number. Each element has a symbol, which is one or two letters. The first letter is always capitalized.

/**
 * I have written this code more generic, if you want then you can group based on any * 
 * instance variable , id, name etc via passing method reference.
**/

class Student {
    private int id;
    private String name;
    public Student(int id, String name) {this.id = id;this.name = name;}
    /**
     * @return the id
     */
    public int getId() {return id;}
    /**
     * @param id
     *            the id to set
     */
    public void setId(int id) {this.id = id;}
    /**
     * @return the name
     */
    public String getName() {return name;}
    /**
     * @param name
     *            the name to set
     */
    public void setName(String name) {this.name = name;}
}

public class StudentMain {

    public static void main(String[] args) {

        List<Student> list = new ArrayList<>();
        list.add(new Student(1, "Amit"));
        list.add(new Student(2, "Sumit"));
        list.add(new Student(1, "Ram"));
        list.add(new Student(2, "Shyam"));
        list.add(new Student(3, "Amit"));
        list.add(new Student(4, "Pankaj"));

        Map<?, List<Student>> studentById = groupByStudentId(list,
                Student::getId);
        System.out.println(studentById);

       Map<?, List<Student>> studentByName = groupByStudentId(list,
                Student::getName);
        System.out.println(studentByName);

    }

    private static <K, V> Map<?, List<V>> groupByStudentId(List<V> list,
            Function<V, K> keyFunction) {
        return list.stream().collect(
                Collectors.groupingBy(keyFunction, HashMap::new,
                        Collectors.toList()));
    }
}

Python, Given a list of elements, write a Python program to group list elements and their respective frequency within a tuple. Examples: Input : [1, 3, 4, 4, 1, 5, 3, 1] Output​  Like the periodic table, the list below organizes the elements by the number of protons in their atoms; it can also be organized by other properties, such as atomic weight, density, and electronegativity. For more detailed information about the origins of element names, see List of chemical element name etymologies .

If you need a grouping while mantaining the order and apply a function(Reduction) perhaps counting i use something like this.

final Map<Integer,Long>map=stream.collect(Collectors.groupingBy(function
   ,LinkedHashMap::new
   ,Collectors.collectingAndThen(Collectors.counting(),Function.identity()))
 )

Python, Let's discuss certain ways to pair elements at specific indices. Method #1 : Using list comprehension + zip() List comprehension can be used to achieve this  Right click the group you want to break up. Choose GroupUngroup. If you create a group and then ungroup it so that you can work on its elements individually, you can easily regroup the objects: Right click one of the objects that was in the original group. Choose GroupRegroup.

Group a list into chunks in Python, More than once I've had to take a list of items and group them. object, it's really just getting the next chunk_size elements from the sequence. In chemistry and atomic physics, the main group is the group of elements whose lightest members are represented by helium, lithium, beryllium, boron, carbon, nitrogen, oxygen, and fluorine as arranged in the periodic table of the elements. The main group includes the elements (except hydrogen,

Create groups from lists with itertools.groupby, Make an iterator that returns consecutive keys and groups from the iterable. The key is a function computing a key value for each element. Dr. Helmenstine holds a Ph.D. in biomedical sciences and is a science writer, educator, and consultant. She has taught science courses at the high school, college, and graduate levels. There are 118 elements on the periodic table. Here's a list of the chemical elements, arranged alphabetically according to IUPAC name:

Grouping, Each group denotes a unique value that expression takes for at least one list element, and all elements are put into one and only one group. Divide numbers from 1 to 10 into even and odd numbers. In chemistry and physics, the main group elements are any of the chemical elements belonging to the s and p blocks of the periodic table. The s-block elements are group 1 (alkali metals) and group 2 (alkaline earth metals). The p-block elements are groups 13-18 (basic metals, metalloids, nonmetals, halogens, and noble gases).

Comments
  • From the example given in docs.oracle.com/javase/8/docs/api/java/util/stream/… it looks like it should compile. Possibly Collectors.toList() instead of toList(), unless you imported it statically?
  • @njzk2 I don't think the toList is the problem - that's statically imported as you say. The LinkedHashMap::new line has the following error in IntelliJ: Bad return type in method reference: cannot convert java.util.LinkedHashMap<java.lang.Object, java.lang.Object> to M
  • the mapping collectors apply to the values so you want p -> p instead of PlaceSummary::getPlaceId
  • @AlexisC. so that would be p -> p.getPlaceId ? so... does that mean I can just use p -> p to refer to "this" element?
  • No p -> p.getPlaceId means that the PlaceSummary grouped values will be mapped by their place id. If you want the instances themselves, just apply the identity function so p -> p.
  • Tried it out in production code - works like a dream thank you. Definitely a misunderstanding of the API.
  • In addition, I preferred placeSummary -> placeSummary to Function.identity() since it seems a bit clearer To clarify as well. The code isn't too wierd if you understand the purpose of it. What I was attempting to do was group duplicate Ids but then filter out duplicates using rules. One of those rules being to keep one of the duplicates based on whether it's an augmented place (we augment places to give them additional information that the Google API doesn't know) or not.
  • Yeah I think that's what confused me a little. I think it would have been preferable to have the argument orders key, value mapping, toList() if I'm honest - but small gripe. Will remember this for future reference... thanks.