mboost-dp1

C# Switch statement med intervaller


Gå til bund
Gravatar #1 - ghostface
8. jul. 2009 09:42
Hey alle

Jeg har en integer med en værdi fra 0 til 100.

For at give en tekstruel præsentation af det tal har jeg nogle intervaller som siger noget om status på tallet.

Til det bruger jeg en switch.

Jeg har dog svært ved at finde en måde hvorpå jeg kan give samme feedback om værdien af 4-5 6-10 10-19 osv.
Jeg ved man i PHP bare kan skrive <5 <20 <30 osv men det lader ikke til at fungere i C#.

Alternativet er at lave fallthrough på de andre tal men når jeg opererer fra 0 til 100 så virker det som det vildeste overkill.

Nogen ideer?
Gravatar #2 - Windcape
8. jul. 2009 09:48

// 1-10
if((val > 0) && (val =< 10)) { }
// 11-20
else if((val > 10) && (val =< 20)) { }


err?

Det er normal logik, og det er ens for alle gængse programmeringssprog. PHP og C# er overhovedet ikke forskelligt på det punkt!
Gravatar #3 - ghostface
8. jul. 2009 10:57
ja det er jo åbenlyst men jeg ville gerne holde det i en switch.
Gravatar #4 - Windcape
8. jul. 2009 11:01
Men det er forkert at ville det. Du switcher på states, ikke på intervaller.

Hvis det er fordi du regner med at forstørrere intervallerne senere, skal du kigge på en helt anden løsning, ved hjælp af nogle design patterns.
Gravatar #5 - arne_v
8. jul. 2009 13:19
Du kan bruge if.

Eller du kan lave et array med 100 elementer og switche paa arr100[val].
Gravatar #6 - ghostface
8. jul. 2009 16:18
jeg endte op med at lave en stor if fucker istedet.

Det må være løsningn indtil videre.

Tak for input.
Gravatar #7 - arne_v
8. jul. 2009 16:41
Givet at grupperingen ikke kan beregnes ved en simpel formel, så er det enten multi if eller conversion array. Multi if er nemmest at læse. Conversion array vil være hurtigst.
Gravatar #8 - Arnfast
9. jul. 2009 20:49
swtich(val / 10){
case 0:
sadas;
break;
..
...

}

det burger at gøre det så tager den i intervallet på 10
Gravatar #9 - arne_v
9. jul. 2009 22:03
#8

Jep.

Men spørgsmålet lød på intervallerne: ... 4-5 6-10 10-19 ... !
Gravatar #10 - Emil Melgaard
11. jul. 2009 22:51
I Pascal/Delphi kan man gøre følgende:

case val of
4..5: EtEllerAndet;
6..10: NogetAndet;
11..19: NogetTredje;
end;


Kan det virkelig passe at der ikke findes noget tilsvarende i C#?

Der findes måske slet sets i C#?
Gravatar #11 - arne_v
11. jul. 2009 23:12
#10

Kun:


switch(val)
{
case 4:
case 5:
EtEllerAndet;
break;
case 6:
case 7:
case 8:
case 9:
case 10:
NogetAndet;
break;
// o.s.v.
}


og det bliver man hurtigt træt af.

Nej. Sets finde kun som library type ikke som indbygget type.

Men dit eksempel bruger vel heller ikke set !?!?
Gravatar #12 - Windcape
11. jul. 2009 23:34

var numbers = Enumerable.Range(0, 10);


(Nu hvor vi er offtopic)
Gravatar #13 - arne_v
12. jul. 2009 00:09
#12

Det er jo heller ikke et set.

Men System.Collections.Generic.HashSet<> er et set.
Gravatar #14 - Windcape
12. jul. 2009 01:38
Afhænger det ikke lidt af hvordan vi definere begrebet "set" ?

I det der linkes til, og i mange andre sprog, som f.eks. C++, representere sets jo bare en List<T> eller et array.

Den eneste forskel ville jo være at det givne set var immutable, men det er

var numbers = Enumerable.Range(0, 10); 


jo også, da det er et Enumerable<Int> der retuneres, og ikke en List<Int>
Gravatar #15 - arne_v
12. jul. 2009 02:53
Windcape (14) skrev:
Afhænger det ikke lidt af hvordan vi definere begrebet "set" ?


Jeg anbefaler at du kigge ud af vinduet for at checke om en forsamling af matematikere gør klar til at lynche dig.

Set er et ret veldefineret begreb.

Gravatar #16 - arne_v
12. jul. 2009 02:56
Windcape (14) skrev:

I det der linkes til, og i mange andre sprog, som f.eks. C++, representere sets jo bare en List<T> eller et array.


Nix.

Prøv og sammenlign disse to stykker næsten ens kode:

using System;
using System.Collections.Generic;
using System.Linq;

namespace E
{
public class Program
{
public static IEnumerable<int> Gen(int start, int count)
{
return Enumerable.Range(start, count);
}
public static void Dump(string lbl, IEnumerable<int> en)
{
Console.Write(lbl + " :");
foreach(int v in en)
{
Console.Write(" " + v);
}
Console.WriteLine();
}
public static void Main(string[] args)
{
var numbers = Gen(0, 10);
Dump("before", numbers);
numbers = numbers.Concat(Gen(9, 2));
Dump("after", numbers);
Console.ReadKey();
}
}
}


using System;
using System.Collections.Generic;
using System.Linq;

namespace E
{
public class Program
{
public static HashSet<int> Gen(int start, int count)
{
return new HashSet<int>(Enumerable.Range(start, count));
}
public static void Dump(string lbl, IEnumerable<int> en)
{
Console.Write(lbl + " :");
foreach(int v in en)
{
Console.Write(" " + v);
}
Console.WriteLine();
}
public static void Main(string[] args)
{
var numbers = Gen(0, 10);
Dump("before", numbers);
numbers.Add(9);
numbers.Add(10);
Dump("after", numbers);
Console.ReadKey();
}
}
}


HashSet garanterer mod duplikater.
Gravatar #17 - arne_v
12. jul. 2009 03:06
Ligesom Pascal set gør.

Her er lidt Delphi pascal kode:

program SetFun;

{$APPTYPE CONSOLE}

uses
SysUtils;

type
range = 0..99;
setrange = set of range;

procedure Dump(lbl : string; en : setrange);

var
v : range;

begin
write(lbl,' :');
for v in en do begin
write(' ',v);
end;
writeln;
end;

var
numbers : setrange;

begin
numbers := [0..9];
Dump('before', numbers);
numbers := numbers + [9..10];
Dump('after', numbers);
readln;
end.
Gravatar #18 - arne_v
12. jul. 2009 03:22
Og ligesom Java gør det:

import java.util.HashSet;
import java.util.Set;

public class SetFun1 {
public static Set<Integer> gen(int start, int count) {
Set<Integer> res = new HashSet<Integer>();
for(int i = start; i < start + count; i++) {
res.add(i);
}
return res;
}
public static void dump(String lbl, Iterable<Integer> en) {
System.out.print(lbl + " :");
for(int v : en)
{
System.out.print(" " + v);
}
System.out.println();
}
public static void main(String[] args) {
Set<Integer> numbers = gen(0, 10);
dump("before", numbers);
numbers.add(9);
numbers.add(10);
dump("after", numbers);
}
}


Det er valgfrit om man vil bruge HashSet eller TreeSet.
Gravatar #19 - Emil Melgaard
12. jul. 2009 09:00
arne_v (11) skrev:
Men dit eksempel bruger vel heller ikke set !?!?


Det kan godt være at det ikke bruger sets. Jeg gik bare ud fra at det var nogenlunde det samme der skete som når jeg skrev:

if val in [4..5] then
EtEllerAndet;
else if val in [6..10] then
NogetAndet;
else if val in [11..19] then
NogetTredje;


Som jo altså bruger sets.

Man kan nemlig også skrive:

case val of
4..5,7: EtEllerAndet;
6,8..10: NogetAndet;
11..19: NogetTredje;
end;


Så det kan godt være at det ikke direkte bruger sets, men jeg synes det minder meget om.

Windcape (12) skrev:
(Nu hvor vi er offtopic)


Jeg beklager at jeg har fået tråden lidt off topic, men det så ud til at han havde fået svar på sit spørgsmål, så jeg tænkte at jeg lige ville høre lidt mere om det, da jeg er ved at lære C#.
Gravatar #20 - lorenzen
12. jul. 2009 12:23
Windcape (14) skrev:
Afhænger det ikke lidt af hvordan vi definere begrebet "set" ?


Nu er jeg ikke matematiker eller står uden foran dit vindue, men eftersom jeg er stor fan af formel methode specifikation så får jeg da arbejdet en smule med sets.

Men den nemmeste def på begrebet set, vil jeg sige er en uordnet mængde af objekter, hvor i der ikke kan optræde duplikeringering. Også kendt som naiv mængde teori, men det virker og bør kunne forståes og accepteres af alle i CS.

De steder hvor vi i CS bruger begreber direkte hentet fra matematikken, så er der ikke et spørgsmål om hvordan vi definere det, der er kun een definition og det er det. Derimod kan der være et spørgsmål om hvordan vi (mis)fortolker et emne, for at tilpasse det til de begrænsninger et givet sprog giver os.

Men det ændrer ikke på at et set er et set og den def bør der slet ikke være diskussion om, fordi ellers kan vi da slet ikke kommunikere entydigt med hinanden om problemstillingerne.
Gravatar #21 - Windcape
12. jul. 2009 13:32
At der tages hensyn til dublikater giver jo så også mening :)

Men det er ret tit i C++ og Pascal at "Set" bliver benyttet til at omtale hvad der i praktis bare et en simpel collection, hvor det faktisk er irrelevant om der er dublikater.

En immutable list fra Enumerable.Range indeholder vel i princippet heller ingen dublikater.
Gravatar #22 - Windcape
12. jul. 2009 13:34
Emil Melgaard (19) skrev:
Jeg beklager at jeg har fået tråden lidt off topic, men det så ud til at han havde fået svar på sit spørgsmål, så jeg tænkte at jeg lige ville høre lidt mere om det, da jeg er ved at lære C#.


Du kan gøre dette her, men det er langsommere end normal if/else, hvis det forbliver så simpelt:


int value = 10;

if(Enumerable.Range(4, 5).Contains(value))
{
// EtEllerAndet
}
else if(Enumerable.Range(6, 10).Contains(value))
{
// NogetAndet
}
else if(Enumerable.Range(11, 19).Contains(value))
{
// NogetTredje
}

Gravatar #23 - Emil Melgaard
12. jul. 2009 14:02
Windcape (22) skrev:
Du kan gøre dette her, men det er langsommere end normal if/else, hvis det forbliver så simpelt:


int value = 10;

if(Enumerable.Range(4, 5).Contains(value))
{
// EtEllerAndet
}
else if(Enumerable.Range(6, 10).Contains(value))
{
// NogetAndet
}
else if(Enumerable.Range(11, 19).Contains(value))
{
// NogetTredje
}



Ok, det undrer mig lidt, for det er det ikke i Pascal:

http://en.wikipedia.org/wiki/Pascal_%28programming_language%29 skrev:
A set is a fundamental concept for modern mathematics, and they may be used in a great many algorithms. Such a feature is highly useful and may be faster than an equivalent construct in a language that does not support sets. For example, for many Pascal compilers:

if i in [5..10] then
...

is faster, than

if (i>4) and (i<11) then
...


Jeg kan godt se at det er muligt at bruge sets i C#, men jeg troede nu at det var implementeret som en special syntax (som i Pascal) og ikke bare som en speciel type.
Gravatar #24 - arne_v
12. jul. 2009 20:01
Emil Melgaard (19) skrev:
Det kan godt være at det ikke bruger sets. Jeg gik bare ud fra at det var nogenlunde det samme der skete som når jeg skrev:

if val in [4..5] then
EtEllerAndet;
else if val in [6..10] then
NogetAndet;
else if val in [11..19] then
NogetTredje;


Som jo altså bruger sets.


Korrekt.

[4..5] er et set.

Men jeg vil ikke kalde 4..5 for et set.

Emil Melgaard (19) skrev:
Jeg beklager at jeg har fået tråden lidt off topic, men det så ud til at han havde fået svar på sit spørgsmål, så jeg tænkte at jeg lige ville høre lidt mere om det, da jeg er ved at lære C#.


Jeg synes da at det er meget forfriskende at få et andet sprog på banen, fordi det kan da godt være lidt trivielt med kun C++/Java/C# måden at gøre tingene på.
Gravatar #25 - arne_v
12. jul. 2009 20:18
Windcape (21) skrev:
Men det er ret tit i C++ og Pascal at "Set" bliver benyttet til at omtale hvad der i praktis bare et en simpel collection, hvor det faktisk er irrelevant om der er dublikater.


set er en kendt STL container i C++.

set er et keyword i Pascal.

Hvis C++ eller Pascal programmører bruger set som betegnelse for en almindelig collection som kan indeholde duplikater, så er den gal.

Windcape (21) skrev:
En immutable list fra Enumerable.Range indeholder vel i princippet heller ingen dublikater.


Korrekt. Men det er initialiseringen ikke typen som sikrer det.
Gravatar #26 - arne_v
12. jul. 2009 20:18
#25

Og C++ kode:

#include <iostream>
#include <vector>
#include <list>
#include <set>

using namespace std;

int main()
{
vector<int> v;
v.push_back(1);
v.push_back(2);
v.push_back(2);
v.push_back(3);
v.push_back(3);
v.push_back(3);
cout << "vector:" << endl;
for(vector<int>::iterator it = v.begin(); it != v.end(); it++)
{
cout << *it << endl;
}
list<int> lst;
lst.push_back(1);
lst.push_back(2);
lst.push_back(2);
lst.push_back(3);
lst.push_back(3);
lst.push_back(3);
cout << "list:" << endl;
for(list<int>::iterator it = lst.begin(); it != lst.end(); it++)
{
cout << *it << endl;
}
set<int> s;
s.insert(1);
s.insert(2);
s.insert(2);
s.insert(3);
s.insert(3);
s.insert(3);
cout << "set:" << endl;
for(set<int>::iterator it = s.begin(); it != s.end(); it++)
{
cout << *it << endl;
}
return 0;
}
Gravatar #27 - arne_v
12. jul. 2009 20:21
Windcape (22) skrev:
Du kan gøre dette her, men det er langsommere end normal if/else, hvis det forbliver så simpelt:


Emil Melgaard (23) skrev:
Ok, det undrer mig lidt, for det er det ikke i Pascal:


Principielt kunne C# compileren og .NET JIT også optimere C# versionen.

Men det gør den ikke idag. Og jeg ved ikke om den nogensinde kommer til det.

Det er noget mere naturligt for en compiler at optimere features i sproget end features der er implementeret i biblioteket.

(omend det er muligt med teknologier som .NET JIT)
Gravatar #28 - arne_v
12. jul. 2009 20:24
Emil Melgaard (23) skrev:
Jeg kan godt se at det er muligt at bruge sets i C#, men jeg troede nu at det var implementeret som en special syntax (som i Pascal) og ikke bare som en speciel type.


Pascal kommer fra en procedural baggrund.

C# var objektorienteret fra start.

Set implementeret i library er noget mere elegant i OOP end i PP.

Jeg gætter på at det er derfor set ikke kom med som indbygget type.

Det er ihvertfald ikke manglende kendskab til Pascal syntax.
Gravatar #29 - Emil Melgaard
12. jul. 2009 20:41
arne_v (28) skrev:
Pascal kommer fra en procedural baggrund.

C# var objektorienteret fra start.

Set implementeret i library er noget mere elegant i OOP end i PP.


Når jeg tænker over det, er det nok også mest i C at jeg har savnet at kunne bruge sets, men det er nok også fordi at jeg altid har været lidt fan af Delphi og Pascal :)

arne_v (28) skrev:
Det er ihvertfald ikke manglende kendskab til Pascal syntax.


Nej, det er det næppe når det nu er samme person er har været med til at udvikle sprogene til det de er i dag :)
Gravatar #30 - Windcape
12. jul. 2009 23:22
arne_v (25) skrev:
Hvis C++ eller Pascal programmører bruger set som betegnelse for en almindelig collection som kan indeholde duplikater, så er den gal.
Dem jeg har snakket med har ikke brugt betegnelsen sådan, men de har benyttet Set som en array, hvor det er rimelig irrelevant for dublikater.

Det samme gælder Emil's eksempel.

Typisk benyttes de netop fordi at de valgte sprog ikke har features til at lave en liste af data fra 1...10 ligesom .NET 3.5 tilbyder.

Og det er hvad der forvirrer mig mest. Når folk benytter forkerte eller irrelevante typer, uden nogen reel grund.
Gravatar #31 - lorenzen
12. jul. 2009 23:37
#30
Det kan godt være at det i array er lige meget duplikater, men sidder du og implementere noget hvor i der ikke skal kunne være duplikater er det væsenligt at du sikre dig dette.

Og hvis du så i din dokumentation skriver set om din implementering, så vil du også implicit skrive at der er sørget for at duplicater ikke kan optræde og iøvrigt alle de andre egenskaber som følger med et set.

Et array er ikke et set, men nok nærmere en sequence, dog med den undtagelse af at rækkefølgens betydning ikke ligger på type niveau men specification. (cirka)

Forkert brugte typer er forfærdeligt, men ligeså er forkert brugte matematiske udtryk. Omend det desværre ofte kan give mening at blive intuitiv naiv matematisk forklaring overfor en PL som spørger ind til noget.
Gravatar #32 - arne_v
12. jul. 2009 23:53
Windcape (30) skrev:
Typisk benyttes de netop fordi at de valgte sprog ikke har features til at lave en liste af data fra 1...10 ligesom .NET 3.5 tilbyder.


Pascal standarden definerer ikke hvordan set skal implementeres, men jeg mener at de normalt implementeres som bitmask.

D.v.s. at et set [1..10] og en liste/array med værdierne 1 til 10 er ret forskellige.

Se f.eks. denne variant:

program MoreSetFun;

{$APPTYPE CONSOLE}

uses
SysUtils;

type
range = 0..99;
setrange = set of range;

procedure Dump(lbl : string; en : setrange);

var
v : range;

begin
write(lbl,' :');
for v in en do begin
write(' ',v);
end;
writeln;
end;

var
numbers : setrange;

begin
numbers := [0,2,4];
Dump('before', numbers);
numbers := numbers + [1,3];
Dump('after', numbers);
readln;
end.


som outputter:

before : 0 2 4
after : 0 1 2 3 4

Nøgleordet som lorenzen allerede nævnte i #20 er "uordnet".

set og liste/array har ikke mere tilfælles end list/array har med map/dictionary.
Gå til top

Opret dig som bruger i dag

Det er gratis, og du binder dig ikke til noget.

Når du er oprettet som bruger, får du adgang til en lang række af sidens andre muligheder, såsom at udforme siden efter eget ønske og deltage i diskussionerne.

Opret Bruger Login