mboost-dp1
C# Switch statement med intervaller
- Forside
- ⟨
- Forum
- ⟨
- Programmering
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?
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?
jeg endte op med at lave en stor if fucker istedet.
Det må være løsningn indtil videre.
Tak for input.
Det må være løsningn indtil videre.
Tak for input.
I Pascal/Delphi kan man gøre følgende:
Kan det virkelig passe at der ikke findes noget tilsvarende i C#?
Der findes måske slet sets i C#?
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#?
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
jo også, da det er et Enumerable<Int> der retuneres, og ikke en List<Int>
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>
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.
Ligesom Pascal set gør.
Her er lidt Delphi pascal kode:
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.
Og ligesom Java gør det:
Det er valgfrit om man vil bruge HashSet eller TreeSet.
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.
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#.
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.
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.
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.
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
}
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.
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å.
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.
#25
Og C++ kode:
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;
}
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)
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.
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 :)
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.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.
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.
#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.
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.
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.