Laden...

Alle Möglichkeiten aus dynamischen Listen generieren lassen

Erstellt von nash128 vor 4 Jahren Letzter Beitrag vor 4 Jahren 1.606 Views
N
nash128 Themenstarter:in
3 Beiträge seit 2019
vor 4 Jahren
Alle Möglichkeiten aus dynamischen Listen generieren lassen

Hallo ins Forum,

ich habe noch nicht viel Erfahrung in der Programmierung, konnte mir bisher aber immer mit Hilfe von Google und der Suchfunktion im Forum hier gut helfen.

Jetzt fehlt mir für eine Aufgabe aber absolut der Ansatz und etwas derartiges habe ich auch noch nirgends gefunden.
Es geht um eine Artikelkonfiguration für ein ERP System. Keine Sorge, der Neuling will KEINEN Konfigurator entwickeln... 😉
Es geht final darum, vom Programm automatisiert eine Liste mit allen möglichen Konfigurationen ausgeben zu lassen, um sie dann in das ERP-System zu importieren.

Folgendermaßen sollte es funktionieren:
Es wird ein Mutterartikel eingegeben (nur Artikelnummerpräfix und Bezeichnung des Artikels) und dann die Optionsgruppen (sind in ihrer Anzahl nicht fix), welche mind. zwei oder mehr Werte haben können.

Die Artikelnummer würde sich aus einem einzugebenden Präfix und dann aus so vielen Stellen, wie es Optionsgruppen gibt zusammensetzen. Jede Stelle verkörpert im Prinzip im Wert die jeweilige Zahl der Option. (Beispiel folgt gleich...)

Beispiel (am Auto, weil für jeden einfacher vorstellbar...):
Eingabe ARTIKELNUMMERPRÄFIX = "GO" und ARTIKELBEZEICHNUNG "VW GOLF"

OPTIONSGRUPPE 1 = Motor
Wert 1 = TSI
Wert 2 = TDI

OPTIONSGRUPPE 2 = Farbe
Wert 1 = Weiß
Wert 2 = Schwarz
Wert 3 = Rot

OPTIONSGRUPPE 3 = Radio
Wert 1 = mit Navi
Wert 2 = ohne Navi

...

Button "Generieren" drücken...

Ergebnis (idealerweise als .TXT tabstopp-getrennt): Artikelnummer | Bezeichnung | Motor | Farbe | Radio | Beschreibung

GO111 | VW Golf | 1 | 1 | 1 | VW Golf, Motor: TSI, Farbe: Weiß, Radio: mit Navi
GO121 | VW Golf | 1 | 2 | 1 | VW Golf, Motor: TSI, Farbe: Schwarz, Radio: mit Navi
GO131 | VW Golf | 1 | 3 | 1 | VW Golf, Motor: TSI, Farbe: Rot, Radio: mit Navi
GO112 | VW Golf | 1 | 1 | 2 | VW Golf, Motor: TSI, Farbe: Weiß, Radio: ohne Navi

usw...

Diese Datei kann dann ins ERP importiert werden, und wenn man dann die richtige Artikelnummer eingibt, erhält man direkt die Konfiguration, welche man braucht. Eine manuelle Eingabe von Artikeln, welche wesentlich umfangreicher sind, wäre zu fehleranfällig.

Ich grüble da jetzt schon ewig dran rum, wie ich das mit einer Schleife realisieren kann, scheitere jedoch gänzlich, da es ja nicht so einfach ist wie ABC und daraus alle Möglichkeiten zu bilden. Schließlich gibt es ja dynamisch viele Gruppen und jede kann theoretisch 2 - 9 Werte haben.
Die Ausbaustufe wäre noch Bedingungen zu definieren, die technisch nicht möglich sich (z.B. rote Farbe gibts nur mit Navi) aber soweit will ich noch gar nicht denken. 8o

Ich erwarte natürlich nicht, dass mir das einer jetzt fertig programmiert! Aber vielleicht kann mir jemand einen Tipp mit nem Ansatz zurufen.

Vielen Dank im Voraus!

LG nash

1.029 Beiträge seit 2010
vor 4 Jahren

Hi,

du liegst richtig, dass das mit einer einzigen Schleife schwierig darstellbar ist. Auf der anderen Seite: Warum nicht mehr als eine Schleife? Deine Optionen lassen sich bislang immer gut als "KeyValuePair<int, string>" darstellen. Das würde zumindest für hart gecodete Optionen sehr simpel funktionieren.

Wenn du die Generierfunktion universeller haben möchtest würde ich empfehlen eine Klasse für die Optionen zu erstellen, die einen Namen und eine List von KeyValuePair<int, string> hat. Anschließend würde ich das kartesische Produkt bilden und aus den so entstandenen Konfigurationsmöglichkeiten den letztendlichen Exportstring bauen. (Die Arbeit hier in 2 Methoden zu splitten sollte das Ganze deutlich übersichtlicher halten)

Da du das ganze wahrscheinlich eh noch stark an deine Bedürfnisse anpassen musst mal ein Beispiel wie das bei mir aussehen würde (ohne das String-Gefrickel):


namespace ConsoleApp8
{
    class Program
    {
        public static void Main(string[] args)
        {
            KeyValuePair<string, string> prefix = new KeyValuePair<string, string>("GO", "VW Golf");
            var group1 = new OptionGroup("Motor", new KeyValuePair<int, string>[]
            {
                new KeyValuePair<int, string>(1, "TSI"),
                new KeyValuePair<int, string>(2, "TDI")
            });
            var group2 = new OptionGroup("Farbe", new KeyValuePair<int, string>[]
            {
                new KeyValuePair<int, string>(1, "Weiß"),
                new KeyValuePair<int, string>(2, "Schwarz"),
                new KeyValuePair<int, string>(3, "Rot")
            });

            var product = CartesianProduct(new[]{group1, group2 }.Select(g => g.Options));
        }

        // Source: https://stackoverflow.com/questions/3093622/generating-all-possible-combinations
        static IEnumerable<IEnumerable<T>> CartesianProduct<T>(IEnumerable<IEnumerable<T>> sequences)
        {
            IEnumerable<IEnumerable<T>> emptyProduct = new[] { Enumerable.Empty<T>()};
            return sequences.Aggregate(emptyProduct,
                (accumulator, sequence) => 
                    from accseq in accumulator 
                    from item in sequence 
                    select accseq.Concat(new[] {item})                          
                );
         }
        static StringBuilder GenerateExportString(KeyValuePair<string, string> prefix, IEnumerable<IEnumerable<KeyValuePair<int, string>>> options)
        {
            var sb = new StringBuilder();
            foreach(var selection in options)
            {
                // hier deinen export-string zusammenschustern, jede "selection" ist dabei eine Konfigurationsmöglichkeit und enthält somit alle Id's und Namen der dafür gewählten Option
            }
            return sb;
        }
    }

    public class OptionGroup
    {
        public string Name {get;set;}

        public IEnumerable<KeyValuePair<int, string>> Options {get; }

        public OptionGroup(string name, IEnumerable<KeyValuePair<int, string>> options)
        {
            Name = name;
            Options = options;
        }
    }
}

656 Beiträge seit 2008
vor 4 Jahren

Statt KeyValuePair bieten sich auch Tuples an, wenn du einen aktuellen Compiler sowie C# Version verwenden kannst:

            var group1 = new OptionGroup("Motor", new []
            {
                (1, "TSI"),
                (2, "TDI")
            });
            var group2 = new OptionGroup("Farbe", new []
            {
                (1, "Weiß"),
                (2, "Schwarz"),
                (3, "Rot")
            });
[...]

    public class OptionGroup
    {
        public string Name {get;set;}

        public IEnumerable<(int ID, string Name)> Options {get; }

        public OptionGroup(string name, IEnumerable<(int ID, string Name)> options)
        {
            Name = name;
            Options = options;
        }
    }

        // Verwendung 1 mit Zugriff über Name:
        static StringBuilder GenerateExportString(KeyValuePair<string, string> prefix, IEnumerable<IEnumerable<(int ID, string Name)>> options)
        {
            var sb = new StringBuilder();
            foreach (var selection in options)
            {
                sb.Append(selection.ID).Append(';').Append(selection.Name);
            }
            return sb;
        }

        // Verwendung 2 mit Deconstruction:
        static StringBuilder GenerateExportString(KeyValuePair<string, string> prefix, IEnumerable<IEnumerable<(int ID, string Name)>> options)
        {
            var sb = new StringBuilder();
            foreach (var (id, name) in options)
            {
                sb.Append(id).Append(';').Append(name);
            }
            return sb;
        }
16.807 Beiträge seit 2008
vor 4 Jahren

Der größte Unterschied in dieser Situation ist, dass Tuples eine class sind und KeyValuePairs struct (beide untescheidet insgesamt natürlich mehr).
Sofern es aber einen "echten Key" gibt, sollte man im Vergleich Tuple vs. KeyValuePair zu letzterem greifen.

656 Beiträge seit 2008
vor 4 Jahren

Nunja, Tuple ist eine Class, das stimmt - aber gemeint waren Named Tuples (die durch ValueTuple) umgesetzt sind; das ist eine Struct. Das Kapitel in der Doku dazu heißt nur "Tuples", drum hab ichs initial nicht näher ausgeführt (weil sowohl die named als auch die unnamed tuple syntax zu ValueTuple führt)

16.807 Beiträge seit 2008
vor 4 Jahren

Gut; Class vs. Struct war auch nur ein Hint, wie wenig Unterschied es an dieser Stelle macht.

Message meines Posts war: wenn Du Daten mit einem Key hast, nimm KeyValuePair (nicht Tuple, oder ValueTuple).
Tuples sind zum Halten von Daten ohne expliziten Key.

N
nash128 Themenstarter:in
3 Beiträge seit 2019
vor 4 Jahren

Zunächst mal vielen Dank für die ausführlichen Antworten! Ich werde mich damit jetzt mal ausführlich befassen und Feedback geben 👍

Beste Grüße

nash