Avatar billede mcgoat Nybegynder
05. juli 2006 - 11:18 Der er 20 kommentarer og
2 løsninger

Hjælp til array sjov

Hej igen..

Er igang med at lave en "command promt". Jeg får skrevet DIR's ud først og derefter filerne..

Men vil gerne have lavet det så den skriver dem blandet alt afhængig af startbogstav, altså sorteret.

Hvordan laver jeg lige det?

Koden:

using System;
using System.Collections.Generic;
using System.Text;

namespace ConsoleApplication1
{
    class Program
    {
        static void Main(string[] args)
        {
            String currentdir = "C:\\";
            String command = "";
            Console.WriteLine("Teh 1337 DOS version");
            Console.WriteLine();

            while (command != "exit")
            {
                Console.Write(currentdir.ToUpper());
                command = Console.ReadLine();
                sendcommand1(command, currentdir);
            }
           
        }

        static void sendcommand1(String commando, String currentdir)
        {
            switch (commando)
            {
                case "dir":
                    long totalsize = 0;
                    int numberoffiles = 0;

                    System.IO.DirectoryInfo dire = new System.IO.DirectoryInfo(@currentdir);
                    Console.WriteLine("Listing files in: " + currentdir.ToUpper());
                    Console.WriteLine("Date      T1me  Size      File");

                    foreach( System.IO.DirectoryInfo dirinfo in dire.GetDirectories("*") )
                    {
                        String dirname = dirinfo.Name;
                        String dirdate = dirinfo.CreationTime.ToString().Substring(0, 16);
                        Console.Write(dirdate + " ");
                        Console.Write(" <DIR>    ");
                        Console.WriteLine(dirname);
                    }

                    foreach (System.IO.FileInfo file in dire.GetFiles("*.*"))
                    {
                        numberoffiles++;
                        long filesize = file.Length;
                        String filename = file.Name;
                        String filedate = file.CreationTime.ToString().Substring(0, 16);
                        int filediff = 10 - filesize.ToString().Length;
                        totalsize += filesize;

                        Console.Write(filedate + "  ");
                        Console.Write(filesize);
                        for (int i = 0; i < filediff; i++)
                        {
                            Console.Write(" ");
                        }
                        Console.Write(filename);
                        Console.WriteLine("");
                    }
                    Console.WriteLine();
                    Console.WriteLine("Number of files: " + numberoffiles.ToString() + " - " + totalsize.ToString() + " bytes");
                    Console.WriteLine();

                    break;
                case "cls":
                    Console.Clear();
                    Console.WriteLine("Teh 1337 DOS version");
                    Console.WriteLine();
                    break;
                case "help":
                    Console.WriteLine("Teh Helpfilzorz");
                    Console.WriteLine("dir - List files in current directory");
                    Console.WriteLine("cls - Clears screen");
                    Console.WriteLine("exit - Exit the program");
                    Console.WriteLine();
                    break;
                case "exit":
                    break;
                default:
                    Console.WriteLine("Unknown Command... Type help for available commands");
                    break;
            }
        }
    }
}
Avatar billede md_craig Nybegynder
05. juli 2006 - 12:51 #1
foreach (FileSystemInfo fsi in dir.GetFileSystemInfos())
{
  Console.WriteLine("{0}    {1}", fsi.Name, fsi.FullName);
}

som et eksempel
Avatar billede md_craig Nybegynder
05. juli 2006 - 12:54 #2
eller der var jeg lige for hurtig... :S

Men der kan du få alle slags ud, smid dem i en liste af en art og sorter listen med en comparer...
Avatar billede md_craig Nybegynder
05. juli 2006 - 13:02 #3
static class Program
    {
        [STAThread]
        static void Main()
        {
            DirectoryInfo dir = new DirectoryInfo(@"d:\");
            List<FileSystemInfo> all = new List<FileSystemInfo>(dir.GetFileSystemInfos());
            FileSystemInfoComparer fsic = new FileSystemInfoComparer();
            all.Sort(fsic);

            foreach (FileSystemInfo fsi in all)
            {
                if (fsi.GetType().Name == "DirectoryInfo")
                    Console.WriteLine("{0}            <DIR>", fsi.Name);
                else if (fsi.GetType().Name == "FileInfo")
                    Console.WriteLine("{0}            ", fsi.Name);
            }
        }
    }

    public class FileSystemInfoComparer : IComparer<FileSystemInfo>
    {
        public int Compare(FileSystemInfo x, FileSystemInfo y)
        {
            StringComparer comp = StringComparer.Create(System.Globalization.CultureInfo.GetCultureInfo("en"), true);
            return comp.Compare(x.Name, y.Name);
        }
    }
Avatar billede mcgoat Nybegynder
05. juli 2006 - 13:19 #4
kigger på det så hurtigt som muligt :)
Avatar billede Slettet bruger
05. juli 2006 - 16:52 #5
md_craig giver en god start. Jeg har et forslag til udvidelse, som du sikkert selv vil have som ønske senere. Jeg har bare givet skelettet. Så kan du selv lege med de to nye compare-funktioner. Derfra hvor du bruger klassen kan du skifte sorteringsmetode med fsic.CurrentSort = FileSystemInfoComparer.SortMethods.Size;

public class FileSystemInfoComparer : IComparer<FileSystemInfo>
    {
        public enum SortMethods
        {
          Name, Size, Date
        }
        public SortMethods CurrentSort;

        public FileSystemInfoComparer()
        {
            CurrentSort = SortMethods.Name;
        }

        public int Compare(FileSystemInfo x, FileSystemInfo y)
        {
            int comp;
            switch(CurrentSort)
            {
                case SortMethods.Name:
                    comp = CompareName(FileSystemInfo x, FileSystemInfo y);
                    break;
                case SortMethods.Size:
                    comp = CompareSize(FileSystemInfo x, FileSystemInfo y);
                    break;
                case SortMethods.Date:
                    comp = CompareDate(FileSystemInfo x, FileSystemInfo y);
                    break;
            }
            return comp;
        }

        public int CompareName(FileSystemInfo x, FileSystemInfo y)
        {
            StringComparer comp = StringComparer.Create(System.Globalization.CultureInfo.GetCultureInfo("en"), true);
            return comp.Compare(x.Name, y.Name);
        }
    }
Avatar billede md_craig Nybegynder
06. juli 2006 - 00:15 #6
Jeps... desuden kunne du også udevide den så den evt. kunne sortere efter flere betingelser, fx hvis du skulle vælge at sortere på Data og to filer har samme date, så kan du dernest sortere på navn eller størelse osv...

Endelig kunne du tilade at ændre den culture info der er i forhold til sortering af navn fx...

Jeg havde det bare sådan lidt at det jo var udvidelser op til dig selv... men nu vi er inde på det ville jeg da tilføje de andre jeg også har overvejet.. ;) altså:

- Sortering efter flere nøgler
- Ændring af Culture
- Accending eller Decending
- Og du kan sikkert finde et par Ideer selv ;)
Avatar billede Slettet bruger
06. juli 2006 - 00:49 #7
Ascending/descending er let. Det kræver bare nogle få ekstra linier:

I klassen:
public bool Ascending;

I Constructoren:
Ascending = true;

Og i den generelle Compare-metode, lige før return-linien:
if(!Ascending) comp *= -1;

Så kan man udefra få sortering til at blive vendt ved at sætte Ascending til false.

Culture er endnu lettere.

Flere nøgler er til gengæld lidt mere bøvlet - med mindre man kan give listens Sort-metode en liste af Comparer-objekter.
Avatar billede arne_v Ekspert
06. juli 2006 - 02:06 #8
umiddelbart ville jeg finde det mere OO'sk at bruge forskellige klasser end
en enkelt klasse med en switch på en enum
Avatar billede md_craig Nybegynder
06. juli 2006 - 12:58 #9
arne v >>

Det kan jo have sine pro og cons, Går ud fra at du taler om State eller Strategy mønsteret her så... Personligt vil jeg så mene at hvis kompleksisteten ikke overstiger det som er i [Kommentar: sandbox - 05/07-2006 16:52:26] vil jeg mene at det måske er lidt Overkill, da et Factory møster også ville være at foretrække i samme omgang så...

Det flytter jo derfor bare den switch der skal til hvis du stadig i dit program skal have muligheden for at vælge alle muligheder...

Omvendt kan man jo sige, at ønsker man at implementere sin Comparer til et gennerelt og fremtidsmessigt formål, (hvilket jeg da nok selv ville foretrække)... så er der da en motivation for State eller Strategy i og med man så bare kan udplukke den sortering man skal bruge i en given situation...
Avatar billede arne_v Ekspert
07. juli 2006 - 03:01 #10
slet ikke - jeg ville bare brug en klasse per sortering - ingen patterns
Avatar billede md_craig Nybegynder
07. juli 2006 - 09:29 #11
Det er da faktisk netop set Strategy pattern så?

Strategy går jo ud på at du har en abstraktion, i dette tilfælde IComparer, som du så arver fra til eksempelvis en

FileSystemInfoNameComparer : IComparer
FileSystemInfoTypeComparer : IComparer
FileSystemInfoDateComparer : IComparer
FileSystemInfoSizeComparer : IComparer

De indeholder jo så hver "algoritmen" til hver deres sortering...
Det er da netop Strategy som jeg kender det???

Eller har jeg helt misforstået hvor det er du vil have flere klasser?
Avatar billede Slettet bruger
07. juli 2006 - 12:15 #12
Det er både en af de store fordele og en af de store ulemper ved patterns. Definitionen af et pattern er "En navngivet beskrivelse af et problem og en løsning", og i mange tilfælde er både problemet og løsningen meget simple, så den eneste bonus, de reelt giver, er navnet.

Dermed kan man sagtens implementere et pattern uden at have tænkt på det - eller helt uden at kende det relevante pattern.
Avatar billede md_craig Nybegynder
07. juli 2006 - 14:31 #13
Ja... men uanset hvad er de gode at lærer og at have tæt på sig... Når man implementere ting er de måske i den situation du beskriver. men kaster man et blik på Fowler's refactoring og de refactoring patters han omtaler...

Det vi har gang i her er faktisk et af de refactorings patterns han omtaler, det er i denne omgang sket uden man sådan lagde så meget mærke til det, men omvendt beskriver de netop kodesituationer, ud fra hans "Replace Type Code with State/Strategy"

Og så kan det give en hurtig overgang til bedre kode, frem for man skal til at "genopfinde" kode...

For lige at vende tilbage til Ascending/decending ville jeg måske være lidt fræk at ordne det med:

private int ascending = 1;
public bool Ascending
{
  get { return this.ascending == 1; }
  set { this.ascending = value ? 1 : -1; }
}

og så skal den bare ganges på hver gang... nogle vil betragte det lidt "dirty", men sagen er at det sparer os for en Conditional statement, og det kan nogle af os godt lide...

(Eller dvs. den Conditional statement vi spare, er jo bare flyttet, men så udføres den kun en gang, og ikke N gange...)
Avatar billede arne_v Ekspert
07. juli 2006 - 21:45 #14
du har faktisk ret i at det matcher beskrivelsen af Strategy pattern

men jeg tænker bare på den som helt normal OO abstrakt metode
Avatar billede arne_v Ekspert
07. juli 2006 - 21:50 #15
jeg bragte emnet på bane fordi der er mange definitioner af OO men en af dem
kunne formuleres som:
  egenskaber modelleres ind i forskellige klasser fremfor at bruge if/switch sætninger
  til at adskille forskellige egenskaber

sådan lidt forsimplet: hvis procedural programmering er goto fri programmering, så
er objekt orienteret programmering switch fri programmering
Avatar billede md_craig Nybegynder
07. juli 2006 - 22:26 #16
Arh... det er jeg så uening i, for Strategy flytter bare switch sætningen, du skal jo et eller andet sted tage stilling til hvilket type comparer du skal bruge hvis nu vi forestillede os at man ville give mulighed for alle algoritmer...

Det er også det man ser ud fra Fowler, nemlig at Switchen flyttes fra klassen der foretager noget (i dette tilfælde vores Comparer)... og over til en Factory

Det er sandt at hvis man laver dette som tidligere nævt, som et framework, så kan man i nogen bruge fjerne switchen... men ellers vil Strategy patternet her lede til noget ala:

public static IComparer GetComparer(ComparingType type)
{
  switch (type)
  {
    case ComparingType.Name:
      return new FileSystemInfoNameComparer();
    case ComparingType.Type:
      return new FileSystemInfoTypeComparer();
    case ComparingType.Date:
      return new FileSystemInfoDateComparer();
    case ComparingType.Size:
      return new FileSystemInfoSizeComparer();
  }
}

I denne sammenhæng ville det måske være hensigtsmæssigt at lave en abstrat base class, fx FileSystemInfoComparer, for så at gøre det mere beskrivende...

Men hvis man vil tilbyde en bruge at vælge mellem sortering, så kan jeg ikke se du kommer uden om en switch... (Jow med 4 if'er, men det det samme)
Avatar billede arne_v Ekspert
07. juli 2006 - 22:44 #17
du kan godt komme uden om switch/if i factory med dynamisk load

men jeg vil slet ikke i den retning

bare kalde med en new af den rigtige comparer

hvis man endelig vil have noget kode med mulighed for at skifte sortering
så skal der en switch/if udenfor men den tror jeg ikke at du slipper
for selvom du har switchen indenfor - den enum værdi skal jo komme et sted fra
Avatar billede md_craig Nybegynder
07. juli 2006 - 23:54 #18
Nu kunne man jo være fræk nok at Caste en int til sin Enum...
I såfald ville man i en Gui Baseret Brugergrænseflade kunne enten bruge inde, eller hvad ved jeg... i en Consol ville man jo bare give de 3 muligheder... så man kunne:

dir -1 -accending ... Eller noget
Avatar billede arne_v Ekspert
08. juli 2006 - 01:10 #19
du kan også bruge index ind i et array

men det kan du også med comparer objekter
Avatar billede mcgoat Nybegynder
25. juli 2006 - 21:50 #20
smid nogle svar :)
Avatar billede Slettet bruger
25. juli 2006 - 22:02 #21
Vi er 3. Hvem af os?

Jeg lægger som svar nu, men hvis du ikke mente mig, så skal du bare afvise.
Avatar billede md_craig Nybegynder
26. juli 2006 - 11:22 #22
svar her fra
Avatar billede Ny bruger Nybegynder

Din løsning...

Tilladte BB-code-tags: [b]fed[/b] [i]kursiv[/i] [u]understreget[/u] Web- og emailadresser omdannes automatisk til links. Der sættes "nofollow" på alle links.

Loading billede Opret Preview
Kategori
IT-kurser om Microsoft 365, sikkerhed, personlig vækst, udvikling, digital markedsføring, grafisk design, SAP og forretningsanalyse.

Log ind eller opret profil

Hov!

For at kunne deltage på Computerworld Eksperten skal du være logget ind.

Det er heldigvis nemt at oprette en bruger: Det tager to minutter og du kan vælge at bruge enten e-mail, Facebook eller Google som login.

Du kan også logge ind via nedenstående tjenester