Создать новые группировки на основе элемента String карты - PullRequest
0 голосов
/ 13 февраля 2019

У меня есть список Objects с именем Coordinates, и каждая координата содержит три значения.Два типа double x, y и одно String имя.Мой код получает в качестве входных данных координаты и группирует их по имени, создавая Map типа <String, List<Object>>.Таким образом, вместо того чтобы иметь пары координат, связанные с именем, у меня есть имя, которое ассоциируется со всеми соответствующими координатами.

EG:

Перед картой:

[0.01,0.51] --> A
[0.01,0.56] --> A
[0.01,0.61] --> A
[0.01,0.66] --> AB
[0.01,0.71] --> ABC
[0.01,0.76] --> ABC

где A, B и C - имена.Если несколько имен появляются вместе, это означает, что они имеют одинаковые координаты.

После карты:

[[0.01,0.01,0.01],[0.51,0.56,0.61]] --> A
[[0.01,0.01], [0.61,0.66]]          --> AB
[[0.01, 0.01], [0.71,0.76]]         --> ABC

Чего я хотел бы добиться, так это отделить каждое имя от группы и связать все координатык этому имени.

Например, что я пытаюсь достичь:

[[0.01,0.01,0.01,0.01,0.01,0.01],[0.51,0.56,0.61,0.66,0.71,0.76]] --> A
[[0.01,0.01,0.01,0.01], [0.61,0.66,0.71,0.76]]                    --> B
[[0.01,0.01], [0.71,0.76]]                                        --> C

Код, который создает Map и группирует их по имени, следующий:

Map<String, List<Coordinates>> newList = coordinateList.stream()
                .collect(Collectors.groupingBy(Coordinates::getName));

Есть ли способ добиться этого?Обратите внимание, что имена, например ABC, не разделены запятыми или пробелами, но если это поможет с возможным решением, я уже знаю, как это сделать (A, B, C).

Класс координат:

public class Coordinates {
    private double X;
    private double Y;
    private String name;

    public Coordinates(double dexp, double dent, String name) {
        this.X=dexp;
        this.Y=dent;
        this.name=name;
    }
    @Override
    public String toString() {
        return "["+X+","+Y+"]";
    }
    public String getName() {
        return name;
    }
    public void setName(String name) {
        this.name = name;
    }
    public double getX() {
        return X;
    }
    public void setX(double x) {
        X = x;
    }
    public double getY() {
        return Y;
    }
    public void setY(double y) {
        Y = y;
    }

}

Пример имен:

STEP(One)
STEP(Two)
STEP(One)STEP(Two)

Ответы [ 2 ]

0 голосов
/ 13 февраля 2019

Оставляя задачу разделения имен для вас и предполагая, что вы не хотите создавать новый Coordinate объект с разделенным именем, вы можете сделать это:

   Map<String, List<Coordinates> > newList = coordinateList.stream()
       .flatMap( c -> split( c.getName() ).stream()
                      .map( sn -> new AbstractMap.SimpleEntry<>(sn, c) ) )
       .collect( Collectors.groupingBy(
                 Map.Entry::getKey, 
                 Collectors.mapping(Map.Entry::getValue, Collectors.toList() ) ) );
0 голосов
/ 13 февраля 2019

Если я правильно вас понимаю, мы предположим, что вы уже легко можете добраться до своей второй карты.Однако это должно работать для любой карты, и вы можете даже немного оптимизировать ее, основываясь на этом.Продвигаясь вперед с этим предположением и используя ваше Map<String, List<Coordinate>>, мы можем накапливать / объединять на основе этого ввода:

Map<String, List<Coordinate>> myComboMap = /* ... */;
Map<String, List<Coordinate>> myAbsoluteMap = new HashMap<>();
myComboMap.forEach((name, coords) -> {
    List<String> names = /* split up name into list, or just iterate */;
    names.forEach(n -> {
        //merge or create the results for each name
        myAbsoluteMap.compute(n, (key, old) -> {
            if (old == null) {
                //copy list to avoid changing old map
                return new ArrayList<>(coords);
            }
            //or append to an existing list
            old.addAll(coords);
            return old;
        });
    });
});

Это также может быть сделано с потоками через #flatMap и Collectors # toMap, однако это решение будетсоздание нескольких объектов, поэтому для простоты я выбрал побочный эффект #forEach.

Примечание : это создаст карту одноименных имен с соответствующими координатами.Вы можете перевернуть эту карту довольно легко (оба должны быть довольно уникальными), хотя я сам не уверен в сценарии использования.Имейте в виду, что если два имени имеют одинаковые координаты на этой карте, то переворачивание карты может привести к потере одного из этих имен.Таким образом, я оставил ответ как есть с именами-> координатами.

...