[.NET] Strings vergelijken / sorteren, numeriek als mogelijk

Pagina: 1
Acties:

Onderwerpen

Vraag


Acties:
  • 0 Henk 'm!

  • NickThissen
  • Registratie: November 2007
  • Laatst online: 09-09 10:50
Ik krijg twee strings als user input data en wil deze met elkaar vergelijken om te bepalen of ze aan een (door de user gekozen) conditie voldoen. De conditie kan zijn "equals", "not equals", "greater than", "greater than or equals", "less than" of "less than or equals".

De strings kunnen soms numeriek zijn, maar vaak ook niet. Als beide strings numeriek zijn, dan wil ik ze graag numeriek vergelijken. Als beiden inputs niet numeriek zijn, dan voldoet de standaard String.Compare.

Met numeriek bedoel ik inclusief floats en doubles etc!

Een paar voorbeelden:
"23" moet kleiner zijn dan "124" (met String.Compare zal 23 groter zijn)
"23" moet groter zijn dan "124a" (want 124a is niet numeriek en 2 > 1).
"23" moet gelijk zijn aan "23.0"
"-23" en "24" moeten numeriek gechecked worden (en niet op de "-")


Is er een handige of zelfs in het framework ingebouwde manier om dit voor elkaar te krijgen? Het enige wat ik voor elkaar kan krijgen is een grote brei aan checks:
- Is het een integer (int.TryParse)? Dan vergelijk als int.
- Is het een double, dan vergelijk als double.
- Is het een float, dan ...
- Etc.

En voor elk type input moet dus ook een switch statement komen voor de verschillende condities...

Op het moment heb ik het nog relatief compact weten te houden maar dit is nog niet volledig:
C#:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
        private bool IsMatch(string value1, string value2)
        {
            int i1, i2;

            switch (ComparisonType)
            {
                case ComparisonTypes.Equals:
                    return value1 == value2;

                case ComparisonTypes.NotEquals:
                    return value1 != value2;

                case ComparisonTypes.GreaterThan:
                    if (int.TryParse(value1, out i1) && int.TryParse(value2, out i2))
                    {
                        return i1 > i2;
                    }
                    return String.Compare(value1, value2, StringComparison.InvariantCulture) > 0;

                case ComparisonTypes.GreaterThanOrEquals:
                    if (int.TryParse(value1, out i1) && int.TryParse(value2, out i2))
                    {
                        return i1 >= i2;
                    }
                    return String.Compare(value1, value2, StringComparison.InvariantCulture) > -1;

                case ComparisonTypes.LessThan:
                    if (int.TryParse(value1, out i1) && int.TryParse(value2, out i2))
                    {
                        return i1 < i2;
                    }
                    return String.Compare(value1, value2, StringComparison.InvariantCulture) < 0;

                case ComparisonTypes.LessThanOrEquals:
                    if (int.TryParse(value1, out i1) && int.TryParse(value2, out i2))
                    {
                        return i1 <= i2;
                    }
                    return String.Compare(value1, value2, StringComparison.InvariantCulture) < 1;
            }
            return false;
        }


Dit checkt alleen nog maar voor integers. En de Equals / NotEquals checkt nog niet goed (dus "23.0" en "23" worden niet gelijk gezien). Als ik dit op deze manier ga uitbreiden voor alle soorten numerieke types dan wordt het een drama...

Het is natuurlijk mogelijk en dan moet ik er maar mee leven, maar ik kan me voorstellen dat er een betere manier is?

Als ik google dan vind ik alleen de standaard replies dat "20" groter is dan "100" omdat 2>1, dat snap ik wel. Het probleem is dat ik de input als numeriek wil vergelijken als dat kan, en anders terug val naar de standaard string compare.

Mijn iRacing profiel

Alle reacties


Acties:
  • 0 Henk 'm!

  • ZaZ
  • Registratie: Oktober 2002
  • Laatst online: 19-08 14:24

ZaZ

Tweakers abonnee

In de visual basic namespace zit een functie IsNumeric. Die kan je gewoon in c# gebruiken. Moet je effe op msdn kijken of ie aan je eisen voldoet

Lekker op de bank


Acties:
  • 0 Henk 'm!

  • NickThissen
  • Registratie: November 2007
  • Laatst online: 09-09 10:50
Maar daar schiet ik volgens mij niks mee op. Ik kan checken of beide strings numeriek zijn, maar dan moet ik alsnog checken of ze ints zijn (en zo ja, vergelijken als int), dan checken of ze floats zijn (en zo ja, vergelijken als floats), etc, etc, etc. Exact hetzelfde kan ik doen als ik de hele IsNumeric check oversla (want dat gebeurt al in de check voor int, check voor float, etc.

Mijn iRacing profiel


Acties:
  • 0 Henk 'm!

  • RobIII
  • Registratie: December 2001
  • Niet online

RobIII

Admin Devschuur®

^ Romeinse Ⅲ ja!

(overleden)
Wat je zoekt is "Natural sort". Zit even mobiel maar google het maar even zelf ;) Voila. Linkje toegevoegd :Y)

Sowieso zie ik niet waarom je 't wiel opnieuw aan 't uitvinden bent met "IsMatch". Waarom niet gewoon een IComparer implementeren?

[ Voor 75% gewijzigd door RobIII op 12-10-2016 23:04 ]

There are only two hard problems in distributed systems: 2. Exactly-once delivery 1. Guaranteed order of messages 2. Exactly-once delivery.

Je eigen tweaker.me redirect

Over mij


Acties:
  • 0 Henk 'm!

  • Gomez12
  • Registratie: Maart 2001
  • Laatst online: 17-10-2023
Ik zou idd kijken of natural sort niet iets voor je is, dat is gewoon veel makkelijker...

Maar vanwege het volgende dingetje vermoed ik dat je er niets aan gaat hebben, maarja het is imho ook een vrij bizarre eis die totaal onlogisch, maargoed : "-23" en "24" moeten numeriek gechecked worden (en niet op de "-")
Of tenminste ik lees het als dat daarin 23 en 24 vergeleken moeten worden en niet -23...

Maar anders :
NickThissen schreef op woensdag 12 oktober 2016 @ 22:25:
Maar daar schiet ik volgens mij niks mee op. Ik kan checken of beide strings numeriek zijn, maar dan moet ik alsnog checken of ze ints zijn (en zo ja, vergelijken als int), dan checken of ze floats zijn (en zo ja, vergelijken als floats), etc, etc, etc. Exact hetzelfde kan ik doen als ik de hele IsNumeric check oversla (want dat gebeurt al in de check voor int, check voor float, etc.
Why so difficult? Het is een beetje afhankelijk van hoever je wilt gaan, je hebt een aantal randgevallen. Maar for common simple use zou ik zeggen int=double(=float) en daar 1 of 2 checks voor schrijven.
Wat is de meerwaarde van een check voor ints als je al een check voor doubles hebt?

Acties:
  • 0 Henk 'm!

  • NickThissen
  • Registratie: November 2007
  • Laatst online: 09-09 10:50
RobIII schreef op woensdag 12 oktober 2016 @ 22:57:
Sowieso zie ik niet waarom je 't wiel opnieuw aan 't uitvinden bent met "IsMatch". Waarom niet gewoon een IComparer implementeren?
Dit is onderdeel van een IComparer, maar de twee objects worden eerst naar string omgezet en daarna (als de user dit als optie kiest) getrimd en naar lowercase gezet. Die code leek me niet heel relevant.

De Natural sort lijkt wel in de buurt te komen. Echter lees ik dat het niet identiek werkt in verschillende versies van Windows en dat is toch wel een deal breaker...

Gomez: het voorbeeld met -23 moet gewoon als -23 gezien worden, m'n punt was juist dat hij "-23" als integer ziet en niet als string moet vergelijken door het eerste niet-numerieke karakter. Niks vreemds dus (maar misschien een beetje nutteloos voorbeeld).

Verder heb je wel een goed punt dat ik niet eerst ints, dan floats en dan doubles hoef te checken, maar dat ik meteen en alleen doubles hoef te checken. Ik dacht echter dat ik een geval had gevonden waarbij dit fout ging, maar dat kan ik me nu niet meer herinneren...

Ik zal het eens gaan proberen. Bedankt zo ver.

Mijn iRacing profiel


Acties:
  • 0 Henk 'm!

  • Sircuri
  • Registratie: Oktober 2001
  • Niet online

Sircuri

Volledig Appelig

Volgens mij heb je maar 1 check. Of ik zie iets heel erg over het hoofd.
- of BEIDE waarden zijn numeriek en kun je dus converteren naar doubles en vergelijken
- of ze zijn NIET beide numeriek en vergelijk je ze dus als strings.

Signature van nature


Acties:
  • 0 Henk 'm!

  • RobIII
  • Registratie: December 2001
  • Niet online

RobIII

Admin Devschuur®

^ Romeinse Ⅲ ja!

(overleden)
NickThissen schreef op donderdag 13 oktober 2016 @ 08:51:
Dit is onderdeel van een IComparer, maar de twee objects worden eerst naar string omgezet en daarna (als de user dit als optie kiest) getrimd en naar lowercase gezet. Die code leek me niet heel relevant.
Waarom return je dan een bool i.p.v. een int? (-1, 0, 1 voor < = >)
NickThissen schreef op donderdag 13 oktober 2016 @ 08:51:
De Natural sort lijkt wel in de buurt te komen. Echter lees ik dat het niet identiek werkt in verschillende versies van Windows en dat is toch wel een deal breaker...
Ja want windows XP en 2003 zijn nog steeds relevant... :? Of heb je recente(re) gevallen gevonden?

There are only two hard problems in distributed systems: 2. Exactly-once delivery 1. Guaranteed order of messages 2. Exactly-once delivery.

Je eigen tweaker.me redirect

Over mij


Acties:
  • 0 Henk 'm!

  • R4gnax
  • Registratie: Maart 2009
  • Laatst online: 06-09 17:51
RobIII schreef op donderdag 13 oktober 2016 @ 10:13:
Ja want windows XP en 2003 zijn nog steeds relevant... :? Of heb je recente(re) gevallen gevonden?
Een groter probleem is dat de natural sort van Windows die je kunt P/Invoken, onder diverse locales niet transitief is; a < b en b < c garandeert dan niet dat a < c. Dat is echter wel een pre-conditie voor het correct functioneren van op sortering gebaseerde operaties in de .NET libraries. Als je deze natural sort functionaliteit toch gebruikt is het mogelijk om in eindeloze loops te belanden.

[ Voor 6% gewijzigd door R4gnax op 14-10-2016 19:30 ]


Acties:
  • 0 Henk 'm!

  • RobIII
  • Registratie: December 2001
  • Niet online

RobIII

Admin Devschuur®

^ Romeinse Ⅲ ja!

(overleden)
R4gnax schreef op vrijdag 14 oktober 2016 @ 19:29:
[...]


Een groter probleem is dat de natural sort van Windows die je kunt P/Invoken, onder diverse locales niet transitief is; a < b en b < c garandeert dan niet dat a < c. Dat is echter wel een pre-conditie voor het correct functioneren van op sortering gebaseerde operaties in de .NET libraries. Als je deze natural sort functionaliteit toch gebruikt is het mogelijk om in eindeloze loops te belanden.
Dat staat allemaal letterlijk in de link uit die post (die linkt naar een ander answer op diezelfde pagina, waar overigens ook een oplossing bij staat ;) ). Het is uiteindelijk aan het gebruikte sorteeralgoritme of daar een eindeloze loop uit zou ontstaan overigens. Het kan ja. Of je het in de praktijk ooit gaat tegenkomen is de vraag, evenals de vraag of het wiel opnieuw uitvinden (mogelijk 'vierkant') zich loont voor de specifieke case.

[ Voor 43% gewijzigd door RobIII op 15-10-2016 01:44 ]

There are only two hard problems in distributed systems: 2. Exactly-once delivery 1. Guaranteed order of messages 2. Exactly-once delivery.

Je eigen tweaker.me redirect

Over mij

Pagina: 1