Algorithmus für Arbeit mit fehlenden Listenelementen?

berndoa

Top Contributor
Hallo, ich programmiere zwar in Python aber meine Frage geht eher generell in Richtung Hilfe beim Algorithmus verfassen/generelles Vorgehen:
Ich habe eine Klasse Trade_Order, deren Objekte unter Anderem Attribute wie order_id, message_id und tp_type haben. (alle Strings, tp_type wird nur den Wert "tp1" oder "tp2" haben)

Wir fangen mit einer leeren Lsite an, der wir nach und nach Trade_order Objekte hinzufügen.
Aus gottgegebenen Gründen fügen wir aber entweder ein Objekt mit tp_type="tp1" hinzu.
oder wir fügen 2 objekte hinzu, die die selbe Message id haben und wo eins "tp1" und das andere "tp2" hat (das objekt mit "tp2" wird nahc dem "tp1" objekt hinzugefügt.
es kann also nicht vorkommen das snur ein objekt mit "tp2" ohne zugehöriges "tp1" objekt eingefügt wird.

Ausserdem sind die order ids der objekte aufsteigend gemäß hinzufügereihefolge (jedes neu hinzugefügte objekt hat eine order id größer aller anderen order ids in der liste).

Diese gesamtliste nennen wir A.


Nun sei eine liste mit order ids gegeben bzw die mit den ids generierte teilliste von A
nennen wir sie B.

Meine Sache ist nun:
Es kann sein dass in der A Liste 2 zueinander gehörige objekte (gleiche message id, eins "tp1" und eins mit "tp2") vorkommen.
aus gründen aber in der B Liste nur noch das "tp2" objekt drin ist und das "tp1" Objekt fehlt.

Falls so ein Fall vorliegt, will ich (mit den infos aus der A Liste) vom "tp1" objekt den wert einer variable "takeprofit" haben und vom "tp2" Objekt die order id.
Diese 2 sachen werden als tupel in einer neuen Liste gespeichert.

Ausserdem wird in der A liste das "tp1" objekt gelöscht und beim "zp2" objekt eine bestimmte methode mit eben gespeicherten infos ausgeführt
sowie ein attriut angepasst.

kurzum die 2 attribute aus tp1 und tp2 objekt auslesen, tp1 objekt rausschmeissen, tp2 objekt mit jenen infos als parameter aufrufen und dessen attribut anpassen.

Klingt umständlich, ist es auch.
Nun scheitere ich aber dran wie ich mit den gegebenen A und B Listen
1. alle paarweise objekte in der A lsite finde (also gleiche message id, eins hat "tp1" eins hat "tp2"), wo in der B liste nur noch das "tp2" objekt existiert aber nicht mehr das "tp1" objekt.

und dann halt auf den "tp1" und "tp2" objekt die genannten Sachen mache.

Komme auf keinen sinnvolllen listen durhclauf algorithmus, gerade weil ich ja elemente teilweise während der iteration aus der A lsite rausschmeisse und so, komme ich nicht weiter.
Auch ob ich eine oder beide lsite vielleicht erst nahc message id, dann nach "tp1"/"tp2"srtieren sollte um mir das suchen dann leichter zu machen, keine Ahnung.
Verzweifle dran und kann mir im Kopf keine sinnvolle Vorgehensweise denken.

Hat Jemand einen guten Plan?
 
Hier mal ein Ansatz, wobei der eigentliche Part in der Methode perform zu finden ist. Der besteht aus zwei Schritten.

  1. In der B-Liste alle tp2-Einträge ohne zugehörigen tp1-Eintrag finden. Dazu werden zuerst die Message-IDs der B-Liste (dort orders) gesammelt, deren tpType gleich tp1 ist. Danach werden alle Message-IDs der B-Liste gesammelt, deren tpType gleich tp2 ist aber nicht in der tp1-Liste enthalten ist. Aus Gründen der Geschwindigkeit werden HashSets verwendet. Der Schritt benötigt lineare Laufzeit.
  2. Die A-Liste (allOrders) wird nach Message-ID gruppiert, die daraus reultierende Map enthält als Key die Message-ID und als Value die Liste aller zur Message-ID gehörigen TradeOrders. Von jedem Eintrag in der Map benötigen wir nur den Wert, d. h. die Liste, aber nur, wenn genau 2 Einträge enthalten sind (tp1 und tp2). Dann wird noch sichergestellt, dass die Message-ID in der tp2-Liste aus Schritt 1 enthalten ist und das wars.

Java:
public class Test {
    private static Random rand = new Random(4L);

    record TradeOrder(String orderId, String messageId, String tpType, BigDecimal takeprofit) {
        void someFunction(String someOrderId, BigDecimal profit) {
            System.out.println("someFunction called on " + this + " with " + someOrderId + ", " + profit);
        }
    }

    public void perform(List<TradeOrder> allOrders, List<TradeOrder> orders) {
        Set<String> tp1Ids = new HashSet<>(getMessageIdsByTpType(orders, "tp1").collect(Collectors.toSet()));
        Set<String> tp2Ids = new HashSet<>(getMessageIdsByTpType(orders, "tp2")
                .filter(Predicate.not(tp1Ids::contains))
                .collect(Collectors.toSet()));

        allOrders.stream()
                .collect(Collectors.groupingBy(TradeOrder::messageId)).values().stream()
                .filter(list -> list.size() == 2)
                .filter(list -> tp2Ids.contains(list.get(0).messageId()))
                .forEach(list -> process(allOrders, list));
    }

    private void process(List<TradeOrder> allOrders, List<TradeOrder> pair) {
        int first = "tp1".equals(pair.get(0).tpType()) ? 0 : 1;
        TradeOrder tp1Order = pair.get(first);
        TradeOrder tp2Order = pair.get(1 - first);

        BigDecimal profit = tp1Order.takeprofit();
        String orderId = tp2Order.orderId();

        allOrders.remove(tp1Order);
        tp2Order.someFunction(orderId, profit);
    }

    private Stream<String> getMessageIdsByTpType(List<TradeOrder> orders, String tpType) {
        return orders.stream().filter(b -> tpType.equals(b.tpType())).map(TradeOrder::messageId);
    }

    public static void main(String[] args) {
        List<TradeOrder> allOrders = createOrders(10);
        List<TradeOrder> orders = new ArrayList<>(allOrders.stream().filter(e -> rand.nextBoolean()).toList());

        System.out.println("All orders: ");
        allOrders.stream().forEach(System.out::println);

        System.out.println("\norders: ");
        orders.stream().forEach(System.out::println);

        // damit auch die Reihenfolge keine Rolle spielt, 
        // einmal durchmischen
        Collections.shuffle(allOrders);
        Collections.shuffle(orders);

        new Test().perform(allOrders, orders);
    }

    private static List<TradeOrder> createOrders(int n) {
        List<TradeOrder> orders = new ArrayList<>();
        for (int i = 0; i < n; i++) {
            String messageId = String.valueOf(rand.nextInt());
            BigDecimal profit = BigDecimal.valueOf(rand.nextDouble()).setScale(2, RoundingMode.HALF_UP);
            orders.add(new TradeOrder(String.valueOf(rand.nextInt()), messageId, "tp1", profit));
            if (rand.nextBoolean()) {
                profit = BigDecimal.valueOf(rand.nextDouble()).setScale(2, RoundingMode.HALF_UP);
                orders.add(new TradeOrder(String.valueOf(rand.nextInt()), messageId, "tp2", profit));
            }
        }
        return orders;
    }

}
 

Zurück
Oben