Laden...

Elegante Lösung für If Abfrage einer Variable auf mehrere zulässige Werte

Erstellt von ludden vor 12 Jahren Letzter Beitrag vor 12 Jahren 4.388 Views
L
ludden Themenstarter:in
55 Beiträge seit 2010
vor 12 Jahren
Elegante Lösung für If Abfrage einer Variable auf mehrere zulässige Werte

Hallo,
ich hoffe ich bin hier richtig, eigentlich ist es keine große Frage aber einen "kurze Frage kurze Antwort Thread" habe ich nicht gefunden.

Jetzt zu meinem Problem:
Seid kurzem Programmiere ich berufsbedingt wieder und bin heute über ein Problem gestoßen über das ich schon seit Jahren nachdenke.

Ich hab eine Variable die versch. Werte annehmen kann. Normalerweise schreit sowas ja nach einem switch case, aber manchmal möchte ich sowas machen


int i = gibMirIrgendEineZahl();
if(i == 1 || i == 2 || i== 4000 || i == 1337 || i = 100)
{
      foo();
}

Sehr unübersichtlich und blöd zu ändern.

Also für jede dieser Bedingungen genau die gleiche Aktion ausführen, weshalb ich einen switch irgendwie als unnötig empfinde er würde ja sowieso so aussehen:


switch(i)
{
case 1 : foo;break;
case 2 : foo;break;
case 4000 : foo;break;
case 1337 : foo;break;
case 100 : foo;break;
}

Das nimmt mir allerdings zuviel Platz weg und extra eine Region definieren halte ich auch für übertrieben.

Jetzt drängt es mich irgendwie sowas zu machen(Achtung pseudocode):


if(i in [1,2,4000,1337,100])
{
      foo();
}

was meiner Meinung nach sehr elegant und kurz wäre. Gibt es sowas und ich bin einfach noch nicht darüber gestolpert? Ich glaub in Python gibt es so ein Konstruckt.

D
216 Beiträge seit 2009
vor 12 Jahren

Hallo ludden,

zum einen guck die mal diesen Thred an, den wir hier vor kurzem hatten: if-schleife mit vielen String-Bedingungen abkürzen....

Zum anderen kann man die switch-Anweisung folgendermaßen verkürzen:

switch(i) {
  case 1:
  case 2:
  case 4000:
  case 1337:
  case 100:
    foo();
    break;
}

Dein unteres Beispiel lässt sich so umsetzen:

int[] bla = new int[] { 1, 2, 4000, 1337, 100 };

if(bla.Contains(i))
  foo();

Edit: Beziehungsweise, näher an deinem Beispiel, wenn auch meiner Meinung nach nicht übersichtlicher:

if((new int[] { 1, 2, 4000, 1337, 100 }).Contains(i))
  foo();

Ich hoffe ich konnte dir helfen,

DarthMaim

2.891 Beiträge seit 2004
vor 12 Jahren

Oder du benutzt eine Erweiterungsmethode:


public static class IsInExtensions
{
	public static bool IsIn<T>(this T value,IEnumerable<T> enumerable)
	{
		return enumerable.Contains(value);
	}

	public static bool IsIn<T>(this T value,params T[] enumerable)
	{
		return enumerable.Contains(value);
	}
}

Aufruf dann wie folgt:


if (i.IsIn(1,2,4000,1337,100))
{ ... }

oder


if (i.IsIn(new[] { 1,2,4000,1337,100 }))
{ ... }

Gruß,
dN!3L

U
1.688 Beiträge seit 2007
vor 12 Jahren

Schnelle Alternative wäre ein HashSet<int>.

1.130 Beiträge seit 2007
vor 12 Jahren

weshalb ich einen switch irgendwie als unnötig empfinde er würde ja sowieso so aussehen:

Warum nicht so:

switch(i)
{
case 1:
case 2:
case 4000:
case 1337:
case 100:
    foo();
    break;
}

Allerdings ist der Vorschlag von ujr für sehr viele Werte deutlich schneller, sofern das HashSet wiederverwendet wird.

Und wiederverwendet heißt meißt statische Variable!

Projekte:Jade, HttpSaver
Zum Rechtschreiben gibts doch schon die Politiker. Aber die bauen auch nur mist!

L
ludden Themenstarter:in
55 Beiträge seit 2010
vor 12 Jahren

Allerdings ist der Vorschlag von ujr für sehr viele Werte deutlich schneller, sofern das HashSet wiederverwendet wird.

Und wiederverwendet heißt meißt statische Variable!

Brauchs eigentlich nur 1x, aber die Idee von Dniel find ich ganz nett 😃

3.170 Beiträge seit 2006
vor 12 Jahren

Hallo,

aber die Idee von Dniel find ich ganz nett 😃

Ja, nette Idee. Aber ich sehe keinen wirklichen Sinn darin eine solche Methode zu schreiben. Sie kehrt im Gegensatz zu Contains lediglich Aufrufinstanz und Parameter um. Sparen tut man dadurch nix, weil man mit denselben Objekten auch direkt Contains verwenden kann. Und zwar immer.

Gruß, MarsStein

Non quia difficilia sunt, non audemus, sed quia non audemus, difficilia sunt! - Seneca

799 Beiträge seit 2007
vor 12 Jahren

Dem gegenüber steht aber die gute Lesbarkeit insofern finde ich das schon ganz nett was dEN!3l da gemacht hat.

Ist natürlich Geschmackssache ob man sich die extra Arbeit für die deklarative Schreibart antut.

As a man thinketh in his heart, so he is.

  • Jun Fan
    Es gibt nichts Gutes, außer man tut es.
  • Erich Kästner
    Krawutzi-Kaputzi
  • Kasperl
1.002 Beiträge seit 2007
vor 12 Jahren

Hallo MarsStein,

ganz so einfach ist es nicht — so lässt sich zum Beispiel dN!3Ls zweite Erweiterungsmethode, die params nutzt, nicht ganz trivial umdrehen, sodass Contains() verwendet werden kann:

if (i.IsIn(1, 2, 4000, 1337, 100))
{ 
    /* ... */
}

Das händische Äquivalent wäre

if (new int[] { 1, 2, 4000, 1337, 100 }.Contains(i))
{ 
    /* ... */
}

Ich halte dN!3Ls Variante auch für deutlich lesbarer! (Gerade den Aspekt Lesbarkeit kommt häufig zu kurz und sollte meiner Meinung nach nicht unterschätzt werden.

m0rius

Mein Blog: blog.mariusschulz.com
Hochwertige Malerarbeiten in Magdeburg und Umgebung: M'Decor, Ihr Maler für Magdeburg

3.170 Beiträge seit 2006
vor 12 Jahren

Hallo zusammen,

gerade im Bezug auf Lesbarkeit finde ich die Variante nicht so gut, weil sie an dem im Framework vorhandenen und durchgängig benutzten Contains vorbei die Methode genau anders rum implementiert.
Auch wird bei der Version mit params für den Quellcodeleser nicht klar, dass hier implizit eine Collection erstellt wird, was durch den ungewohnten Methodennamen nicht besser wird.

-> Man sieht einfach nicht so gut was passiert (meine persönliche Meinung)

Gruß, MarsStein

Non quia difficilia sunt, non audemus, sed quia non audemus, difficilia sunt! - Seneca

2.891 Beiträge seit 2004
vor 12 Jahren

Dniel [...] dEN!3l

dN!3L

Meine Methode hat auch einzig den Zweck, die Parameterreihenfolge zu tauschen. Je nach Anwendungsfall liest es sich so besser (Stichwort Yoda Conditions). Und in Anlehnung z.B. an den SQL-Befehl i IN (1,23,456).

Gruß

Information von herbivore vor 12 Jahren

Bitte streitet euch nicht um des Kaisers Bart!

Jeder kann selbst entscheiden, was er nutzen möchte.

M
6 Beiträge seit 2011
vor 12 Jahren

Was hier noch nicht erwähnt wurde: in VB.Net gibts noch den Befehl IIF, klappt allerdings nur mit 2 Werten aber den setze ich gerne bei Return-Anweisungen ein, spart ein paar Zeilen 😃

Wie der in C# heißt weiß ich allerdings leider nicht.

C
1.214 Beiträge seit 2006
vor 12 Jahren

OMG. Ein Grund mehr, VB nicht zu verwenden.

In Sprachen mit C Syntax macht man das mit ?. Hat aber nichts mit der ursprünglichen Frage zu tun.

1.346 Beiträge seit 2008
vor 12 Jahren

return a > b ? 1 : 2;

jetzt ist aber gut hier mit offtopic. Sonst gibts haue von herbivore