Avatar billede majbom Novice
04. december 2006 - 19:52 Der er 19 kommentarer og
2 løsninger

indsætte manglende tal i streng

hejsa experter :)

jeg har før spurgt om dette (http://www.eksperten.dk/spm/710861), men er kommet i problemer igen...

jeg har en streng: ",1,2,3,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20," - uden gåseøjne. nu vil jeg gerne have sat "4," ind mellem "...,3," og "5,...", så der står: "...,3,4,5,...", det gør jeg således:

int i;
string[] arr = str.Split(',');
for (i = 1; i < arr.Length - 1; i++)
{
int val = Int32.Parse(arr[i]);
if (val > space) break;
}
str = str.Insert(2 * i-1, space.ToString() + ",");

og det virker meget godt så længe tallene er et-cifrede, men ligeså snart at de er 2- eller 3-cifrede vil den kage i det og sætte tallet ind midt i et andet tal.
jeg har så prøvet at lave

"str = str.Insert(2 * i-1, space.ToString() + ",");"

om til

"str = str.Insert((2 * i)-(i.ToString().Length), space.ToString() + ",");"

det virker ikke rigtigt, for den tæller det antal pladser op og trækker det antal cifre tallet er på fra, men den når ikke helt op til tallet, da f.eks. 10 bliver talt for to pladser i strengen...

håber i forstår hvad jeg skriver, det kan jo godt være svært at forklare :)
er der et klogt hovede der har en løsning på mit problem?

på forhånd tak
Avatar billede zappa Nybegynder
04. december 2006 - 20:15 #1
Prøv dette:

string str = "1,2,3,4,6,7,8,9";
int i;
string[] arr = str.Split(',');
int space = 5;
int val = 0;
for (i = 1; i < arr.Length - 1; i++)
{
  val = Int32.Parse(arr[i]);
  if (val > space) break;
}
int index = str.IndexOf(val.ToString());
str = str.Insert(index-1,","+space.ToString());

Kan der være to ens tal i rækkefølgen?
Avatar billede majbom Novice
04. december 2006 - 20:35 #2
hey najs, det virker!

mange tak smid lige et svar :)

der kan ikke være 2 ens tal i strengen...
Avatar billede bulgroz Nybegynder
04. december 2006 - 20:44 #3
Må jeg foreslå en alternativ løsning:


            // Definer din sorterede liste. Egentligt har du ikke brug for "value" i denne løsning.
            System.Collections.Generic.SortedList<int, int> sortedList = new SortedList<int, int>();

            #region Fyld demodata...
           
            int space = 100; // Ved ikke hvad værdien er den er ikke med i dit eksempel
            string inputString = ",1,2,3,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,";
            string[] inputArray = inputString.Split(',');
            for (int i = 0; i < inputArray.Length; i++)
            {
                int value = 0;

                if (Int32.TryParse(inputArray[i], out value))
                {
                    sortedList.Add(value, value);
                }

                if (value > space) break;
            }

            #endregion // Fyld demodata...

            #region Eksempel på indsættelse af ny værdi...

            int newValue = 4;

            try
            {
                sortedList.Add(newValue, newValue);
            }
            catch(ArgumentException)
            {
                MessageBox.Show(string.Format("Værdien '{0}' findes allerede!", newValue));
            }
           
            #endregion // Eksempel på indsættelse af ny værdi...


            #region Ekempel på udskrift...

            StringBuilder stringBuilder = new StringBuilder();
            stringBuilder.Append(','); // Det første komma, hvis det er et krav

            // Eksisterende værdier...
            foreach (int value in sortedList.Keys)
            {
                stringBuilder.AppendFormat("{0},", value);
            }

            MessageBox.Show(stringBuilder.ToString());
           
            #endregion // Ekempel på udskrift...
Avatar billede zappa Nybegynder
04. december 2006 - 20:56 #4
Svar.
Avatar billede majbom Novice
04. december 2006 - 22:09 #5
-> bulgros - jeg kan ikke helt få det til at virke, jeg får fejl ved:

System.Collections.Generic.SortedList<int, int> sortedList = new SortedList<int, int>();
den siger at "the non-generic type 'System.Collection.Generic.SortedList' cannot be used with type arguments"
Avatar billede majbom Novice
04. december 2006 - 22:23 #6
jo jeg fik det til at virke, skulle bare lige skrive: "using System.Collections.Generic" i toppen og fjerne "System.Collections.Generic" foran SortedList i dit eksempel. så nu virker det perfekt, og jeg slipper for det første komma, og derved bliver det pænere rent grafisk, mange tak for hjælpen begge 2.
smider ikke lige et svar også bulgros? så kan i dele pointene :)
Avatar billede bulgroz Nybegynder
04. december 2006 - 22:27 #7
Svar.
Avatar billede bulgroz Nybegynder
04. december 2006 - 22:27 #8
Ups... Svar :-)
Avatar billede arne_v Ekspert
06. december 2006 - 04:38 #9
selvom string med komma separerede tal er et højest upraktisk format at operere
på, så generer det mig alligevel at indsættelse i sorteret liste er blevet
en O(n) operation

illustrativ/forvirrende kode:

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

namespace E
{
    public class MainClass
    {
        public static string InsertValueInCommaList1(string s, int val)
        {
            string[] a = s.Split(',');
            for (int i = 1; i < a.Length - 1; i++)
            {
                if (int.Parse(a[i]) > val)
                {
                    return s.Insert(s.IndexOf("," + a[i] + ","), "," + val);
                }
            }
            return s + val + ",";
        }
        public static string InsertValueInCommaList2(string s, int val)
        {
            SortedList<int, int> lst = new SortedList<int, int>();
            string[] a = s.Split(',');
            for (int i = 1; i < a.Length - 1; i++)
            {
                int v = int.Parse(a[i]);
                lst.Add(v, v);
            }
            lst.Add(val, val);
            StringBuilder sb = new StringBuilder();
            sb.Append(',');
            foreach (int v in lst.Keys)
            {
                sb.Append(v);
                sb.Append(',');
            }
            return sb.ToString();
        }
        private static int FindLeadingComma(string s, int ix)
        {
            int res = ix;
            while(s[res] != ',') res--;
            return res;
        }
        private static int FindTrailingComma(string s, int ix)
        {
            int res = ix + 1;
            while(s[res] != ',') res++;
            return res;
        }
        private static int FindValue(string s, int ix)
        {
            int lead = FindLeadingComma(s, ix);
            int trail = FindTrailingComma(s, ix);
            return int.Parse(s.Substring(lead + 1, trail - lead - 1));
        }
        public static string InsertValueInCommaList3(string s, int val)
        {
            if(s.Length <= 1) return "," + val + ",";
            int low = 1;
            if(FindValue(s, low) > val) return "," + val + s;
            int high = s.Length - 2;
            if(FindValue(s, high) < val) return s + val + ",";
            while(low < high)
            {
                int piv = (low + high) / 2;
                int pivval = FindValue(s, piv);
                if(pivval < val)
                {
                    low = FindTrailingComma(s, piv);
                }
                else if(pivval > val)
                {
                    high = FindLeadingComma(s, piv);
                }
                else
                {
                    throw new ArgumentException(val + " already in list");
                }
            }
            return s.Substring(0, low + 1) + val + s.Substring(high);
        }
        private const int N = 100;
        private const int REP = 1000;
        public static void Main(string[] args)
        {
            string s = ",1,2,3,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20," ;
            Console.WriteLine(InsertValueInCommaList1(s, 4));
            Console.WriteLine(InsertValueInCommaList2(s, 4));
            Console.WriteLine(InsertValueInCommaList3(s, 4));
            Console.WriteLine(InsertValueInCommaList1(s, 0));
            Console.WriteLine(InsertValueInCommaList2(s, 0));
            Console.WriteLine(InsertValueInCommaList3(s, 0));
            Console.WriteLine(InsertValueInCommaList1(s, 21));
            Console.WriteLine(InsertValueInCommaList2(s, 21));
            Console.WriteLine(InsertValueInCommaList3(s, 21));
            int[] v = new int[N];
            Random rng = new Random();
            for(int i = 0; i < v.Length; i++)
            {
                int newv;
                do
                {
                    newv = rng.Next(2*N);
                }
                while(Array.IndexOf(v, newv) >= 0);
                v[i] = newv;
            }
            long t1 = DateTime.Now.Ticks;
            for(int j = 0; j < REP; j++) {
                string s1 = ",";
                for(int i = 0; i < v.Length; i++)
                {
                    s1 = InsertValueInCommaList1(s1, v[i]);
                }
            }
            long t2 = DateTime.Now.Ticks;
            Console.WriteLine(String.Format("1: {0,10}",(t2 - t1)));
            long t3 = DateTime.Now.Ticks;
            for(int j = 0; j < REP; j++) {
                string s2 = ",";
                for(int i = 0; i < v.Length; i++)
                {
                    s2 = InsertValueInCommaList2(s2, v[i]);
                }
            }
            long t4 = DateTime.Now.Ticks;
            Console.WriteLine(String.Format("2: {0,10}",(t4 - t3)));
            long t5 = DateTime.Now.Ticks;
            for(int j = 0; j < REP; j++) {
                string s3 = ",";
                for(int i = 0; i < v.Length; i++)
                {
                    s3 = InsertValueInCommaList3(s3, v[i]);
                }
            }
            long t6 = DateTime.Now.Ticks;
            Console.WriteLine(String.Format("3: {0,10}",(t6 - t5)));
            Console.ReadLine();
        }
    }
}
Avatar billede bulgroz Nybegynder
06. december 2006 - 07:44 #10
Nu har det imidlertid aldrig været tænkt som at den sortede liste skal fyldes med værdier hver gang man indsætter en ny, hvilket sker i dit eksempel.
Avatar billede majbom Novice
06. december 2006 - 09:20 #11
-> arne_v - hvad vil du fortælle? jeg er ikke lige med...
Avatar billede bulgroz Nybegynder
06. december 2006 - 14:50 #12
At løsningen med SortedList er dyr at anvende, i forhold til array løsninger hvis listen fyldes med grunddata hver gangman indsætter en ny værdi.

Og det er naturligis rigtigt.

Valg af løsning kommer an på hvor ofte det hænder at du skal indsætte en ny værdi i din streng. Ved mange indsætninger vil SortedList løsningen være at foretrække, vel og mærke hvis listen udbygges undervejs, og ikke som i arnes eksempel, fyldes med alle data hver gang der indsættes en ny værdi.
Avatar billede majbom Novice
06. december 2006 - 14:54 #13
nå okay... men det jeg skal bruge det til er det sjældent det sker, så det går nok :)
Avatar billede arne_v Ekspert
06. december 2006 - 16:36 #14
jeg vil bare pointere at der er nogle principielle problemer med tilgangen til problemet

de er ikke noedvendigvis relevante for dig, men hvis nogen laeser den har traad om
3 aar synes jeg at det skal naevnes
Avatar billede majbom Novice
06. december 2006 - 17:22 #15
okay, bare i orden så :)

kan du så evt. forklare mig hvad det er der ikk er optimalt ved bulgroz' løsning?
Avatar billede arne_v Ekspert
06. december 2006 - 18:33 #16
problemerne er:
1) brug af string til opbevaring af data
2) maader at indsaette i den string paa som kraever gennemloeb af hele stringen
Avatar billede majbom Novice
06. december 2006 - 18:43 #17
okay, hvordan mener du så at jeg skal opbevare data'ene?
Avatar billede bulgroz Nybegynder
06. december 2006 - 18:46 #18
?
At opbevare data i en streng er helt klart usmart, men har intet med min løsnng at gøre (det var opgavens krav).
Avatar billede bulgroz Nybegynder
06. december 2006 - 18:48 #19
Er det data du gemmer?
Avatar billede arne_v Ekspert
06. december 2006 - 18:52 #20
data boer opbevares i en indexeret data struktur int[], List<int>,
SortedList<int,int> eller andre - der er faktisk en del muligheder
Avatar billede majbom Novice
06. december 2006 - 18:54 #21
okay... data og data, det er jo så tal fra 1 - (nogle hundrede stykker)... det er vel osse en slags data? :)
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