mboost-dp1

Dynamisk array-allokering


Gå til bund
Gravatar #1 - XorpiZ
24. aug. 2010 07:38
Mojn!

Har lidt bøvl med et program. Har en input-fil med forskellige oplysninger, som jeg skal have lavet om til en kommasepereret fil. Ikke det store problem i sig selv, men der er lige en catch.

Outputformatet er:

2,X,dato, voresSEnr,landekode,kundesSEnr,beløb

Problemet er, at i input-filen kan en bestemt kunde godt optræde flere gange, men i output-filen må kunden kun optræde én gang.

Jeg har lavet et string-array hvor alle linjerne bliver gemt, men jeg kan ikke lige gennemskue, hvordan jeg skal søge i det array efter kundenummeret - og hvis det eksisterer, hvordan jeg så skal lægge beløbet sammen.

Jeg overvejede at lave et multidimensionelt array, men så vidt jeg kan se, så kan man ikke lave et der bliver dynamisk allokeret alt efter størrelsen.

Har i nogle bud på, hvad jeg kan gøre?
Gravatar #2 - Mamad (moveax1ret)
24. aug. 2010 07:43
du skal aldrigt bruge arrays(medmindre du koder c) brug en mere sikker container, f.eks. en vector.

i dette tilfælde skal du bruge en hashmap/dictionary alt efter hvilket sprog du bruger.
Gravatar #3 - XorpiZ
24. aug. 2010 07:46
Jeg kiggede lidt på dictionary (det er C# forresten) - men så vidt jeg kom frem til, så understøtter den kun 2 kolonner.. jeg skal helst bruge 7 :/
Gravatar #4 - Mamad (moveax1ret)
24. aug. 2010 07:47
så laver du da bare et dictionary med vectors i fjolle :)
Gravatar #5 - XorpiZ
24. aug. 2010 07:49
Der fik jeg lige instant headache heh.

Jeg læser lige lidt op på det :)
Gravatar #6 - XorpiZ
24. aug. 2010 07:50
Kan det passe at i C# hedder det arraylists, og ikke vectors?
Gravatar #7 - arne_v
24. aug. 2010 07:55
#6

Hvis du bruger .NET 1.1 er det ArrayList - i .NET 2.0, 3.0, 3.5 og 4.0 skal du bruge List<>.
Gravatar #8 - Mamad (moveax1ret)
24. aug. 2010 07:55
yarh
Gravatar #9 - XorpiZ
24. aug. 2010 07:57
Fornemt - dem kigger jeg på. Jeg vender frygteligt tilbage, hvis jeg får problemer med dem (det gør jeg). :)
Gravatar #10 - arne_v
24. aug. 2010 07:58
#1

Mit forslag:
- lav en data klasse X med 7 properties
- brug en Dictionary<string,X> til at opbevare data i
- læs ind i den (duplikater bliver automatisk overskrevet når du bruger f.eks. kundeSEnr som key)
- iterer over den og udskriv
Gravatar #11 - fidomuh
24. aug. 2010 08:07
#10

- læs ind i den (duplikater bliver automatisk overskrevet når du bruger f.eks. kundeSEnr som key)


Det er bare super-fail hvis kunden ikke har praecis samme data, eller det ikke er den 'sidste' der indlaeses, der skal vaere den der gemmes :)

Han kunne gemme det i endnu en vector, saa han faar alle entries med for alle kunder og saa finde noget at sortere efter bagefter. :)
Gravatar #12 - arne_v
24. aug. 2010 08:17
#11

????

når du bruger f.eks. kundeSEnr som key
Gravatar #13 - fidomuh
24. aug. 2010 08:48
#12

...?

Saa hvis jeg har 2 styk data:

SE, Navn, Ordrenummer
2300, fido, 2300
2300, fido, 2301

Saa er det OK at der bare staar 2301 i ordrenummer?

[add]
og hvis det eksisterer, hvordan jeg så skal lægge beløbet sammen.


Han skal laegge beloebet sammen, saa er det ikke nok at den overskriver.
Gravatar #14 - Windcape
24. aug. 2010 10:32
#13

Keys er normalt unikke!
Gravatar #15 - Daniel-Dane
24. aug. 2010 10:35
Hold da kæft, hvor er C'erne dog bøvlet, når det kommer til at lave en simpel tabel.
Gravatar #16 - arne_v
24. aug. 2010 10:36
fidomuh (13) skrev:

Saa hvis jeg har 2 styk data:

SE, Navn, Ordrenummer
2300, fido, 2300
2300, fido, 2301

Saa er det OK at der bare staar 2301 i ordrenummer?


Det var hvad der blev bedt om.

i output-filen må kunden kun optræde én gang

fidomuh (13) skrev:

Han skal laegge beloebet sammen, saa er det ikke nok at den overskriver.


Korrekt. Så er han nødt til at opdatere. Men Dictionary<string,X> virker også fint til det.
Gravatar #17 - onetreehell
24. aug. 2010 11:08
Øv, så troede jeg lige det var C. :(
Gravatar #18 - Windcape
24. aug. 2010 11:27
XorpiZ (3) skrev:
Jeg kiggede lidt på dictionary (det er C# forresten) - men så vidt jeg kom frem til, så understøtter den kun 2 kolonner.. jeg skal helst bruge 7 :/


var datitz = new List<Tuple<int, string, DateTime, int, int, int, Decimal>>();
Gravatar #19 - fidomuh
24. aug. 2010 11:33
#16

Pointen var mere at det ikke er "nok" at han bare overskriver feltet :)
Jeg ved godt at dictionary vil vaere fint til det.

#14

Det er de skam ogsaa her, keysne er ikke problemet. :)
Gravatar #20 - XorpiZ
24. aug. 2010 12:25
Hvis nogen skulle have interesse, så lavede jeg en liste inspireret af:

http://www.c-sharpcorner.com/uploadfile/camurphy/c...

Sorterede mine poster først efter landekode og så efter SENr via:

            kunder = kunder
.OrderBy(x => x.countryCode)
.ThenBy(x => x.custSENr)
.ToList();


og så et fint lille stykke slamkode til at tjekke om der er ens SEnr efter hinanden:

            int numberOfRecs = kunder.Count; //hent antal records
int counter1 = 0;
int counter2 = 1;
while (counter2 < numberOfRecs)
{
if (kunder[counter1].custSENr == kunder[counter2].custSENr)
{
kunder[counter1].amount = kunder[counter1].amount + kunder[counter2].amount;
kunder.RemoveAt(counter2);
numberOfRecs--;
}
counter1++;
counter2++;
}


Der mangler så bare lige et tjek på, om amount er et plusbeløb eller et minusbeløb, men det er småting. :)

Tak for hjælpen til alle!
Gravatar #21 - KC
24. aug. 2010 12:34
Jeg var ellers klar på en super løsning, men så så jeg at der ikke stod Dynamit array-allokering...
Gravatar #22 - Windcape
24. aug. 2010 13:13
XorpiZ (20) skrev:
og så et fint lille stykke slamkode til at tjekke om der er ens SEnr efter hinanden:
Totally!

Vi kunne jo også linqify det (Og så slipper du for at skulle sortere det først!)


var result =
from kunde in kunder
group kunde by kunde.custSENr
into grouped
select new Kunde()
{
custSENr = grouped.Key,
Amount = grouped.Sum(k => k.Amount),
};
Gravatar #23 - arne_v
24. aug. 2010 13:21
#22

Nu er der flere felter end de 2 ...
Gravatar #24 - arne_v
24. aug. 2010 13:22
#20

Jeg mener stadigvæk at løsningen med Dictionary og fjernelse af duplikater ved indlæsning er den rigtige løsning.
Gravatar #25 - Windcape
24. aug. 2010 13:25
#23

Nu skal du ikke være kedelig!

Jeg er enig desuden enig med #24, men jeg keder mig i en introduktionsklasse til .NET pt. (for det sociale, har faktisk merit :p)
Gravatar #26 - arne_v
24. aug. 2010 13:28
#20

Jeg er iøvrigt ikke overbevist om at koden virker korrekt.

Når du kalder RemoveAt *og* tæller counter2 op - kan der så ikke smutte en igennem?
Gravatar #27 - arne_v
24. aug. 2010 13:29
Windcape (25) skrev:
Nu skal du ikke være kedelig!


Jeg tror faktisk at det vil gøre LINQ løsningen noget mere grumset.
Gravatar #28 - Windcape
24. aug. 2010 13:32
#27

Måske. Men det er jo netop en groupering og herefter en applikation af en funktion herefter.

Hvis jeg har forstået ideen rigtig, er det at groupere, og lægge alting i gruppen sammen, her til et enkelt produkt.

Afhæning af datakilden, kunne man nok godt læse det direkte ud i det grouperede format med LINQ, som kunne blive pænere end alm. kode.

Det er så en smagssag, om man kan lide DSL eller ej :p
Gravatar #29 - arne_v
24. aug. 2010 13:36
#28

Kan LINQ lave en "MySQL GROUP BY"?

Altså em GROUP BY som har:
- felter som grupperes efter
- aggregerede funktioner
- andre felter hvor der tages en værdi fra en tilfældig række
Gravatar #30 - XorpiZ
24. aug. 2010 13:40
arne_v (26) skrev:
#20

Jeg er iøvrigt ikke overbevist om at koden virker korrekt.

Når du kalder RemoveAt *og* tæller counter2 op - kan der så ikke smutte en igennem?


Jo - det har jeg også rettet siden. Nu tæller den kun counter1 & 2 op, hvis der ikke er et hit. :)

LINQ løsningen ser enkel ud, men jeg forstår den ikke hehe. Så hellere nogle gode gammeldags løkker. :D
Gravatar #31 - arne_v
24. aug. 2010 17:51
XorpiZ (30) skrev:
Jo - det har jeg også rettet siden.


Så burde du skrive det.

Der skal nok være en eller anden som om 5 år opggogler og kopierer koden.
Gravatar #32 - XorpiZ
24. aug. 2010 17:57
arne_v (31) skrev:
Så burde du skrive det.

Der skal nok være en eller anden som om 5 år opggogler og kopierer koden.


God ide - jeg paster lige den opdaterede version i løbet af i morgen, når den er testet igennem.

Og du har nok ret i din antagelse, eftersom det program jeg laver skal bruges til dataudtræk fra Navision og så til momsindgivelse til Skat. Kunne forestille mig, at jeg ikke er den eneste i DK, der har det problem, da Skat skifter format nu her. :)

I øvrigt, så var vores gamle "program" et VB script på knapt 900 linjer uden kommentarer. Det var helt tilbage fra 2004 og var kropumuligt at rette noget som helst i, da alle variabel navne hed X, Y og tal, groft sagt.

Men ok, det har nok ikke været meningen, at det skulle rettes i :)
Gravatar #33 - arne_v
5. sep. 2010 00:56
#32

Så alle verdens internetbrugere venter spændt.
Gravatar #34 - Mamad (moveax1ret)
5. sep. 2010 05:02
Gravatar #35 - XorpiZ
5. sep. 2010 06:45
Ak ja. Det havde jeg glemt alt om.

Må lige se om jeg ikke husker det mandag :<
Gravatar #36 - KC
7. sep. 2010 11:28
XorpiZ (35) skrev:
Ak ja. Det havde jeg glemt alt om.

Må lige se om jeg ikke husker det mandag :<


Det gjorde du ikke. Jeg er også ham fra #34...
Gravatar #37 - XorpiZ
7. sep. 2010 11:37
For satan jeg er glemsom.. man skulle ikke tro, at jeg kun er 26 :/

            int counter1 = 0;
int counter2 = 1;

while (counter2 < numberOfRecs)
{
//Tjek om to efterfølgende rækker (række1 & 2) er ens - hvis ja, slet række 2 og tilføj beløbet til række 1
//Tjek igen om række1 & 2 er ens - hvis nej, gå videre og tjek om række 2 & 3 er ens
if (kunder[counter1].custSENr == kunder[counter2].custSENr)
{
//Tjek om beløbet i række2 er negativt
if (kunder[counter2].amount < 0)
{
//Tjek om beløbet i række1 er negativt (hvis ja, så skal de to negative tal lægges sammen og ikke trækkes fra)
if(kunder[counter1].amount < 0)
kunder[counter1].amount = kunder[counter1].amount + kunder[counter2].amount;
else
kunder[counter1].amount = kunder[counter1].amount - kunder[counter2].amount;

}
else
{
kunder[counter1].amount = kunder[counter1].amount + kunder[counter2].amount;
}
//Fjern linjen, der bliver lagt sammen med sin "makker"
kunder.RemoveAt(counter2);
//Træk én fra antal rækker, da vi sletter en ovenfor
numberOfRecs--;

}
else
{
counter1++;
counter2++;
}

}


Så må der grines af min slamkode og mine kommentarer.. jeg har ikke lige gidet fjerne dem :D
Gravatar #38 - XorpiZ
7. sep. 2010 11:38
http://pastebin.com/jcEsTUNM

Det er nok nemmere at læse der :)
Gravatar #39 - onetreehell
7. sep. 2010 16:31
Er listen sorteret efter custSENr? Hvis ikke kan du godt risikere dupletter.

oh, og hvad går det gøgl ud på med at tjekke om den ene eller den anden er negativ?
Gravatar #40 - XorpiZ
7. sep. 2010 20:20
Ja det er den. Først efter landekode og så efter SEnr, så den skulle være i vinkel.

Der er nok en smartere måde at lave tjekket på, men du får lige et eksempel:

amount1 er -10
amount2 er -10

oprindeligt havde jeg bare en funktion, der lagde dem sammen eller trak dem fra hinanden, alt efter om amount1 var positiv eller negativ.

I ovenstående eksempel lavede den altså -10 - -10, hvilket gav 0, istedet for -20, som var planen. Så jeg lavede et grimt lille hack, så det virkede som det skulle :)
Gravatar #41 - qed
7. sep. 2010 20:57
Hvorfor ikke lade være med at tjekke, om nogle af tallene er negative?

10+10 = 20
10+(-10) = 0
(-10)+(-10) = -20

Eller er der noget, jeg har misforstået?
Gravatar #42 - XorpiZ
7. sep. 2010 21:19
Hmm. Det er en fin pointe, du har dig der.

Jeg må lige teste det ved lejlighed. Det er ikke højeste prioritet lige nu, da programmet som sådan virker som det skal. Der mangler godt nok lidt småting, men jeg kigger lige på det ved lejlighed :)
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