Wie füllen Sie zwei separate Arrays aus einer durch Kommas getrennten Liste?

Ich habe eine durch Komma getrennte Textdatei, die 20 durch Kommata getrennte Ziffern enthält. Diese Zahlen repräsentieren erarbeitete Punkte und mögliche Punkte für zehn verschiedene Aufgaben. Wir verwenden diese, um ein Endergebnis für den Kurs zu berechnen.

Normalerweise würde ich die Zahlen durchlaufen, zwei Summen erstellen, teilen und damit fertig werden. Unsere Zuweisung schreibt jedoch vor, dass wir die Liste der Zahlen in zwei Arrays laden.

also das:

10,10,20,20,30,35,40,50,45,50,45,50,50,50,20,20,45,90,85,85

wird das:

int[10] earned   = {10,20,30,40,45,50,20,45,85};
int[10] possible = {10,20,35,50,50,50,20,90,85};

Im Moment benutze ich

for (x=0;x<10;x++)
{
     earned[x] = scores[x*2]
     poss  [x] = scores[(x*2)+1]
}

Das gibt mir die Ergebnisse, die ich will, aber scheint übermäßig klobig.

Gibt es einen besseren Weg?

0
Sie könnten x bis zu 20 in Zweierschritten ausführen. Das entfernt die obskure Multiplikation.
hinzugefügt der Autor usr, Quelle
@Guvante stimmt. War keine gute Idee.
hinzugefügt der Autor usr, Quelle
Du könntest verdient [x/2] , wenn du um zwei erhöhen möchtest.
hinzugefügt der Autor Tim S., Quelle
@ usr: Dann könntest du nicht verdient [x] .
hinzugefügt der Autor Guvante, Quelle
Was Sie tun könnten, um den Code etwas robuster zu machen, ist, laden Sie die ganze Liste in ein Array und verwenden Sie dann foreach, um durch jeden Abschnitt dieses vollständigen Arrays zu scrollen und dann einen Zähler zu verwenden, um zu bestimmen, wie oft Sie die Schleife durchlaufen haben. Wenn der Zähler ungerade ist, geht er in das verdiente Array, oder wenn er gerade ist, geht er in das Ergebnisfeld, wodurch die Multiplikation entfernt wird, und wenn sich die Größe der Liste ändert, besteht keine Notwendigkeit, den Code zu ändern
hinzugefügt der Autor jgok222, Quelle

7 Antworten

Befreien Sie sich von den "magischen" Multiplikationen und unleserlichen Array-Index-Berechnungen.

var earned = new List();
var possible = new List();
for (x=0; x

Dies hat sehr wenig, was einen Textkommentar erfordern würde. Dies ist der Goldstandard für selbstdokumentierenden Code.

Anfangs dachte ich, die Frage sei wegen der ganzen unverständlichen Indexierung eine C-Frage. Es sah aus wie Zeigermagie. Es war zu schlau.

In meinen Codebasen habe ich normalerweise eine AsChunked Erweiterung, die eine Liste in Stücke der angegebenen Größe aufteilt.

var earned = new List();
var possible = new List();
foreach (var pair in scores.AsChunked(2)) {
     earned.Add(pair[0]);
     possible.Add(pair[1]);
}

Jetzt ist die Bedeutung des Codes offensichtlich. Die Magie ist weg.

Noch kürzer:

var pairs = scores.AsChunked(2);
var earned = pairs.Select(x => x[0]).ToArray();
var possible = pairs.Select(x => x[1]).ToArray();
0
hinzugefügt
@MAV dann am Ende ToArray aufrufen.
hinzugefügt der Autor usr, Quelle
@MAV Ich würde das nicht richtig von der Hand nehmen. Auch das macht es zu einer verrückten Aufgabe.
hinzugefügt der Autor usr, Quelle
Da dies eine Zuweisung ist, könnten die Arrays eine Anforderung sein.
hinzugefügt der Autor MAV, Quelle
" unsere Zuweisung schreibt vor, dass wir die Liste der Zahlen in zwei Arrays laden ". Ich interpretiere das so, dass Listen von Anfang an verboten sind. Aber wenn dies eine gültige Lösung für die OP-Zuweisung ist, sage ich, gehen Sie dafür.
hinzugefügt der Autor MAV, Quelle

I would leave your code as is. You are technically expressing very directly what your intent is, every 2nd element goes into each array.

Die einzige Möglichkeit, diese Lösung zu verbessern, besteht darin, zu kommentieren, warum Sie multiplizieren. Aber ich würde erwarten, dass jemand den Trick schnell erkennt oder einfach reproduziert, was er tut. Hier ist ein excessive Beispiel, wie Sie es kommentieren können. Ich würde nicht empfehlen, dies direkt zu verwenden.

for (x=0;x<10;x++)
{
     //scores contains the elements inline one after the other
     earned[x] = scores[x*2]     //Get the even elements into earned
     poss  [x] = scores[(x*2)+1] //And the odd into poss
}

Wenn Ihnen die Multiplikation jedoch nicht gefällt, können Sie den Scores-Index separat verfolgen.

int i = 0;
for (int x = 0; x < 10; x++)
{
    earned[x] = scores[i++];
    poss  [x] = scores[i++];
}

Aber ich würde wahrscheinlich Ihre Version bevorzugen, da es nicht von der Reihenfolge der Operationen abhängt.

0
hinzugefügt
Ich denke, das doppelte Inkrement von ich ist schwer zu verstehen. Eine Zustandsänderung ist schwieriger zu folgen als funktionale Ausdrücke.
hinzugefügt der Autor usr, Quelle
@ usr: Ich stimme zu, es gibt nicht wirklich einen "sauberen" Weg, dies zu tun, was ich auszudrücken versuchte.
hinzugefügt der Autor Guvante, Quelle

Im folgenden sollte jeder alternierende Eintrag die Liste in die anderen beiden Listen aufteilen.

int[20] scores = {10,10,20,20,30,35,40,50,45,50,45,50,50,50,20,20,45,90,85,85};

int[10] earned;
int[10] possible;

int a = 0;
for(int x=0; x<10; x++)
{
    earned[x] = scores[a++];
    possible[x] = scores[a++];
}
0
hinzugefügt
Du hast zwei Probleme. x/y wird oft verwendet, um Matrixmath zu behandeln, was Sie hier nicht tun. Auch jetzt, wenn Sie die internen Linien umdrehen, erhalten Sie völlig unterschiedliche Ergebnisse.
hinzugefügt der Autor Guvante, Quelle
@Guvante Ich habe meine Antwort geändert, um Verwechslungen mit Matrix Mathematics zu vermeiden
hinzugefügt der Autor AeroX, Quelle

Ich nehme an, du könntest es so machen:

int[] earned = new int[10];
int[] possible = new int[10];
int resultIndex = 0;

for (int i = 0; i < scores.Count; i = i + 2)
{
    earned[resultIndex] = scores[i];
    possible[resultIndex] = scores[i + 1];
    resultIndex++;
}

Sie müssen sicher sein, dass eine gleiche Anzahl von Werten in scores gespeichert ist.

0
hinzugefügt

Sie können LINQ hier verwenden:

var arrays = csv.Split(',')
                .Select((v, index) => new {Value = int.Parse(v), Index = index})
                .GroupBy(g => g.Index % 2, 
                         g => g.Value, 
                         (key, values) => values.ToArray())
                .ToList();

und dann

var earned = arrays[0];
var possible  = arrays[1];
0
hinzugefügt
var res = grades.Select((x, i) => new {x,i}).ToLookup(y=>y.i%2, y=>y.x)
int[] earned = res[0].ToArray();
int[] possible = res[1].ToArray();

Dies gruppiert alle Klassen in zwei Buckets basierend auf dem Index, dann können Sie einfach ToArray tun, wenn Sie das Array-Formular benötigen.

0
hinzugefügt

Hier ist ein Beispiel für meinen Kommentar, sodass Sie den Code unabhängig von der Listengröße nicht ändern müssen:

ArrayList Test = new ArrayList { "10,10,20,20,30,35,40,50,45,50,45,50,50,50,20,20,45,90,85,85" };

        int[] earned = new int[Test.Count/2];
        int[] Score = new int[Test.Count/2];

    int Counter = 1;//start at one so earned is the first array entered in to
    foreach (string TestRow in Test)
    {
        if (Counter % 2 != 0)//is the counter even
        {
            int nextNumber = 0;
            for (int i = 0; i < Score.Length; i++)//this gets the posistion for the next array entry
            {
                if (String.IsNullOrEmpty(Convert.ToString(Score[i])))
                {
                    nextNumber = i;
                    break;
                }
            }
            Score[nextNumber] = Convert.ToInt32(TestRow);
        }
        else
        {
            int nextNumber = 0;
            for (int i = 0; i < earned.Length; i++)//this gets the posistion for the next array entry
            {
                if (String.IsNullOrEmpty(Convert.ToString(earned[i])))
                {
                    nextNumber = i;
                    break;
                }
            }
            earned[nextNumber] = Convert.ToInt32(TestRow);
        }
        Counter++

    }
0
hinzugefügt
Es wurde wahrscheinlich abgelehnt, da es eine Reihe von Fehlern in Ihrer Antwort gibt. Ich habe versucht, den Code auszuführen, und es funktioniert nicht. Auch das Konvertieren eines int in eine Zeichenfolge, um zu testen, ob NullOrEmpty ineffizient ist, insbesondere, wenn Sie es in einer für -Schleife tun Zählen, wie viele Elemente Sie bereits in ein int -Array eingefügt haben. Es wäre viel effizienter, die Array-Position in einer Variablen zu verfolgen. Ich habe ein
hinzugefügt der Autor AeroX, Quelle
kann ich fragen, warum die down vote? Dies ist eine alternative Lösung für das Problem, die genau das ist, was die Frage verlangte
hinzugefügt der Autor jgok222, Quelle