Alle möglichen Kombinationswerte von <Flags> Enum berechnen

  • VB.NET

Es gibt 9 Antworten in diesem Thema. Der letzte Beitrag () ist von VB1963.

    Alle möglichen Kombinationswerte von <Flags> Enum berechnen

    Ich habe eine Datenbank übernommen, welche ein Feld beinhaltet, in dem Werte gespeichert sind, die aus einem <Flags> Enum Block kommen. Beim Bearbeiten habe ich festgestellt, dass dort auch ungültige Werte eingetragen sind. Da es sich um über 50000 Einträge handelt die betroffen sein könnten, würde ich gerne ein Programm schreiben, mit dem ich diese ungültigen Werte auf 0 setzen kann. Dazu kommt, dass das Prinzip der Enum Flags Neuland für mich ist und ich nicht einfach alle Werte addieren kann, da es auch "A oder B" Möglichkeiten gibt. Hier mal der stilisierte Enum Block:

    VB.NET-Quellcode

    1. <Flags> Public Enum Values As Integer
    2. Option1A = 2
    3. Option1B = 4
    4. Option2A = 8
    5. Option2B = 16
    6. Option3 = 32
    7. Option4 = 64
    8. End Enum


    1A und 1B sowie 2A und 2B können niemals zusammen auftreten, ansonsten sind alle Kombinationen möglich.

    Gibt es zum Berechnen aller möglichen Kombinationen eine Funktion welche alle Kombinationen in einem Array ausgibt, die ich übersehe, oder muss ich diese selbst schreiben? Stehe da gerade etwas auf dem Schlauch ||

    Dieser Beitrag wurde bereits 1 mal editiert, zuletzt von „VB1963“ ()

    typx schrieb:

    Berechnen aller möglichen Kombinationen
    Da Enums nur gewissermassen "benannte Zahlen" sind, ergeben sich alle möglichen Kombinationen aus allen Werten, die der Zugrundeliegende Zahltyp annehmen kann.
    Also bei Public Enum BlaBla As Int16 wären das 2^16, bei Int32 2°32 usw.



    Aber vlt. verstehe ich die Problematik nicht.

    Wieso sagst du in deim Beispiel "1A und 1B sowie 2A und 2B können niemals zusammen auftreten" - ist ja Quatsch, natürlich können die zusammen auftreten:

    VB.NET-Quellcode

    1. dim _1A1B = Values.Option1A OR Values.Option1B
    Also versuch nochmal eine korrekte eindeutige Problembeschreibung.
    Da die Enum nur Werte zwischen 2 und 64 hat können auch nur Werte in diesem bereich sein, egal in welcher kombination.

    Da also nicht viel in Frage kommt, kann man hier eine Schleife 2 bis 64 nuzten, eine 2 ist Binär 10, eine 4 ist 100. Da eine Kombination von 2 und 4(2 or 4) nicht "legal" ist, brauch man nur testen, ob beim Wert der Schleife das 2. und 3. Bit gesetzt ist. Bei der 2. "illegalen kombination" das gleiche halt nur mit dem 4. und 5. Bit.

    catonmat.net/blog/low-level-bi…you-absolutely-must-know/

    VB.NET-Quellcode

    1. Private Sub PrintLegals()
    2. For i = 2 To 64
    3. Dim legal As Boolean = True
    4. If ((i And (1 << 1)) <> 0) Then
    5. If ((i And (1 << 2)) <> 0) Then
    6. legal = False
    7. End If
    8. End If
    9. If ((i And (1 << 3)) <> 0) Then
    10. If ((i And (1 << 4)) <> 0) Then
    11. legal = False
    12. End If
    13. End If
    14. If legal Then
    15. Debug.WriteLine(i)
    16. End If
    17. Next
    18. End Sub

    Cloud Computer? Nein Danke! Das ist nur ein weiterer Schritt zur totalen Überwachung.
    „Wer die Freiheit aufgibt, um Sicherheit zu gewinnen, wird am Ende beides verlieren.“
    Benjamin Franklin
    hmm - ich find das nicht gut, dasserda iwelche Vorschläge für irgendwas bekommt, obwohl seine Frage vollkommen unausgegoren und unverständlich ist.
    Da probierter dann stundenlang mit herum und lenkt sich ab von dem, wasser nu eiglich wirklich zu tun hat: nämlich seine Frage richtig stellen.

    Weil das hier
    Gibt es zum Berechnen aller möglichen Kombinationen eine Funktion welche alle Kombinationen in einem Array ausgibt?
    kann seine Frage nicht sein, bzw. die Antwort lautet nein, weil bein Enum As Integer ergäbe sich ein Array der Größe 2^32, und das kann man nicht bilden, und wenn mans könnte hätte man nicht die Geduld, es zu befüllen.

    Aber vlt. bezieht er die Frage auch auf das konkret gezeigte Enum - da wäre es möglich, weil das hat nur 6 Member, das Lösungs-Array hätte also die Größe 2^6 = 64.

    Aber auch das glaub ich nicht, dasser das gemeint hat, also nochmal: bitte warten, bis er seine Frage richtig stellt, dass man auch sinnvoll drauf antworten kann.
    Bin gerade leider nur mit dem Handy online, kann später am PC nochmal konkreter auf die Posts eingehen.

    Versuche schon mal, das Problem genauer zu beschreiben.

    In der Datenbank dürfen Werte verschiedenster Kombinationen der Flags vorkommen. Bezogen auf das oben genannte Beispiel zB 4 (Option1B), 12 (Option1B + Option2A), 42 (Option1A + Option2B + Option3) usw.
    Leider sind einige der Felder falsch befüllt, zB mit einer 7. Ich soll nun all diese Werte, die keine gültige Summe beliebiger Werte des Enums sind, auf 0 setzen. Dafür bräuchte ich natürlich aber zuerst alle gültigen Summen, um vergleichen zu können.
    Ich hoffe, so ist es deutlicher beschrieben :)

    typx schrieb:

    Dafür bräuchte ich natürlich aber zuerst alle gültigen Summen, um vergleichen zu können.


    Also ich würde eher sagen, das du die Illegalen brauchst, gezielt die Datensätze mit den illegalen hohlen und dort jeweils das Feld auf 0 setzen. Mit den legalen allein, viel Spass beim suchen. :D Bei meinem Beispiel werden alle legalen Zahlen gelistet, auch wenn sie nicht vorkommen können. Demnach ist auch eine 3 legal, aber keine der Kombinationen wäre 3. In meinem Code musst du nur eine Zeile ändern, dann hast du alle nicht legalen Werte aus allen Kombinationsmöglickeiten. Ausserdem Addiert diese Werte nicht. Durch BitwiseOperations werden die "gebildet". MIr war jedensfalls verständlich was gemeint war.

    000000001 = 1
    000000010 = 2
    -------------------- 1 or 2
    000000011 = 3


    000001010 = 10
    000001011 = 11
    -------------------- 10 or 11
    000001011 = 11

    docs.microsoft.com/de-de/dotne…cal-and-bitwise-operators



    Cloud Computer? Nein Danke! Das ist nur ein weiterer Schritt zur totalen Überwachung.
    „Wer die Freiheit aufgibt, um Sicherheit zu gewinnen, wird am Ende beides verlieren.“
    Benjamin Franklin

    Dieser Beitrag wurde bereits 2 mal editiert, zuletzt von „NoIde“ ()

    typx schrieb:


    In der Datenbank dürfen Werte verschiedenster Kombinationen der Flags vorkommen. Bezogen auf das oben genannte Beispiel zB 4 (Option1B), 12 (Option1B + Option2A), 42 (Option1A + Option2B + Option3) usw.
    Leider sind einige der Felder falsch befüllt, zB mit einer 7. Ich soll nun all diese Werte, die keine gültige Summe beliebiger Werte des Enums sind, auf 0 setzen. Dafür bräuchte ich natürlich aber zuerst alle gültigen Summen, um vergleichen zu können.
    So, jetzt kann man vernünftig anfangen.
    Also das Enum enthält nur 1-Bit-Member, und definiert so, welche Datenbank-Werte legal sind: nämlich nur die Kombinationen von Bits, welche als Member auch im Enum definiert sind.
    Und du brauchst eine Methode CheckDataBaseValue(value as Integer)As Boolean
    Ein Array aller möglicher Summen brauchst du dafür überhaupt nicht, sondern das wird sehr einfach mit Bit-And abgefackelt.

    Momentchen...

    VB.NET-Quellcode

    1. Public Class DBValidator
    2. <Flags>
    3. Private Enum ValidFlags As Integer
    4. Option1A = 2
    5. Option1B = 4
    6. Option2A = 8
    7. Option2B = 16
    8. Option3 = 32
    9. Option4 = 64
    10. End Enum
    11. Private Shared _Bitmask As Integer = 0
    12. Shared Sub New()
    13. For Each enm In DirectCast([Enum].GetValues(GetType(ValidFlags)), ValidFlags())
    14. _Bitmask = _Bitmask Or enm
    15. Next
    16. End Sub
    17. Public Shared Function CheckDataBaseValue(value As Integer) As Boolean
    18. Return (value And _Bitmask) = value
    19. End Function
    20. End Class

    Dieser Beitrag wurde bereits 3 mal editiert, zuletzt von „ErfinderDesRades“ ()

    @typx
    Als Ergänzung:
    ich habe dies noch universal für beliebige Enum's gestaltet:

    VB.NET-Quellcode

    1. Public Class [Enum](Of T As {Structure, IConvertible})
    2. Public Shared Function IsValueValid(value As Integer) As Boolean
    3. If Not GetType(T).IsEnum Then Return False
    4. Dim _HaveFlagsAttribute = GetType(T).CustomAttributes.Any(Function(attr) attr.AttributeType.Name = "FlagsAttribute")
    5. Dim _ListEnum = [Enum].GetValues(GetType(T)).Cast(Of Object)
    6. If _HaveFlagsAttribute Then
    7. Dim _Bitmask As Integer = 0
    8. _ListEnum.ToList.ForEach(Sub(e) _Bitmask = _Bitmask Or CInt(e))
    9. Return (value And _Bitmask) = value
    10. Else
    11. Return _ListEnum.Any(Function(e) CInt(e) = value)
    12. End If
    13. End Function
    14. End Class
    Aufrufen kann man die Funktion dann so:

    VB.NET-Quellcode

    1. <Flags>
    2. Public Enum ValidFlags As Integer
    3. Option1A = 2
    4. Option1B = 4
    5. Option2A = 8
    6. Option2B = 16
    7. Option3 = 32
    8. Option4 = 64
    9. End Enum
    10. Public Enum TestEnumX As ULong
    11. a = 7
    12. b = 31
    13. c = 77
    14. End Enum
    15. Public Enum TestEnumY As Byte
    16. a
    17. b
    18. c
    19. End Enum
    20. result1 = [Enum](Of ValidFlags).IsValueValid(28)
    21. result2 = [Enum](Of TestEnumX).IsValueValid(31)
    22. result3 = [Enum](Of TestEnumY).IsValueValid(2)