Java 4D-Array in 4D-ArrayList umwandeln

Ich glaub für mehr als eine Dimension ist die ArrayList nicht geeignet oder?
Du könntest in eine ArrayList ArrayLists stecken aber hübsch ist das wohl auch nicht. Vllt weiß ja jemand anderes noch rat.
 
Ich möchte es etwa so haben:

Code:
String[][][][] myArray = new String[9][9][9][9];
		
ArrayList<List<List<List<String>>>> myList = new ArrayList<List<List<List<String>>>>();
		
myList = Arrays.asList(myArray);

der letzte Teil mit Arrays.asList(myArray); wird natürlich rot unterringelt.

Weiß einer von euch eine funktionierende Lösung?
 
Natürlich bietet Java dafür keine out-of-the-box Lösung. Es gibt schließlich auch keinen 4D-Array Datentyp.

Die Umwandlung von
Code:
int[][][][]
nach
Code:
List<List<List<List<Integer>>>>
ergibt auf jeden Fall 'ne lustige Schleife, die man sich danach ausdrucken und damit die Wand tapezieren sollte ;)

Ich frag mich nur, warum die lieber mit 'ner ArrayList arbeiten willst? Die Umwandlung von 4D-ArrayList -> 4D-Array ist auf jeden Fall PAIN(!!), weil jede ArrayList eine andere Länge haben kann (musst dann jeweils das Maximum suchen) und ein normales Array eine statische Größe hat.


EDIT: Hier hast du ein Beispiel für 2D: http://stackoverflow.com/a/11447971/1321564
Die Übertragung auf 4D ist nur noch Fleißarbeit.
 
Zuletzt bearbeitet:
In einem 4D-Array kann man doch auch nach Inhalten suchen oder bin ich jetzt vom Mond? =)
 
Autsch

Code:
int position= Arrays.binarySearch(array, wert);

Dabei war ich doch schon so weit ;-P

Code:
private static ArrayList<List<List<List<String>>>> create4DArrayList (String[][][][] myArray)
{
	ArrayList<List<List<List<String>>>> myList = new ArrayList<List <List <List <String>>>>();
		
	return myList;
}

Trotzdem würds mich noch interessieren ob jemand ne Lösung hat.

Soweit ich weiß sind 4D-Arrays recht Lahm, wies bei ArrayListen ist weiß ich nciht
 
Zuletzt bearbeitet:
Ich denke mal, er meint "contains", aber das ist dann auch schon der einzige Vorteil. durch "remove" würde man die ursprüngliche array-Struktur ja zerstören. und evtl. könnte man noch "sort" benutzen.

Also hier ist der code für 4D - eine copy&paste Lösung, kann sicherlich noch schöner gemacht werden ;)

Code:
int[][][][] a = new int[1][1][1][4];
a[0][0][0][0] = 1;
a[0][0][0][1] = 2;
a[0][0][0][2] = 3;
a[0][0][0][3] = 4;

List<List<List<List<Integer>>>> l = new ArrayList<>();
for(int a1 = 0; a1 < a.length; a1++) {
	List<List<List<Integer>>> l1 = new ArrayList<>();
	l.add(l1);
	for(int a2 = 0; a2 < a[a1].length; a2++) {
		List<List<Integer>> l2 = new ArrayList<>();
		l1.add(l2);
		for(int a3 = 0; a3 < a[a1][a2].length; a3++) {
			List<Integer> l3 = new ArrayList<>();
			l2.add(l3);
			for(int a4 = 0; a4 < a[a1][a2][a3].length; a4++) {
				l3.add(a[a1][a2][a3][a4]);
			}
		}
	}
}

for(List<List<List<Integer>>> l1 : l) {
	for(List<List<Integer>> l2 : l1) {
		for(List<Integer> l3 : l2) {
			for(Integer i : l3) {
				System.err.println(i);
			}
		}
	}
}

Btw: "List<List<List<List<Integer>>>> = new ArrayList<>()" ist valider Java7 Code.

ArrayLists werden in Java auch nur als normales Array behandelt (inkl. etwas extra-Speicher, weil bei sonst bei jedem "add" eine Kopie des gesamten Arrays im Speicher erzeugt werden müsste)


Kannst ja einfach mal in den Source Code der arrayList schauen:
Code:
public ArrayList(int initialCapacity) {
    this.elementData = new Object[initialCapacity];
}
Wie du siehst: Es wird intern ein stinknormales Object-Array angelegt.


EDIT: Das mit dem "extra-Speicher" war eine Lüge. Das passiert wohl nur bei der HashMap. Eine ArrayList ist exakt so groß wie man sie anlegt, bzw. wenn man keine Größe angibt, wird "10" gewählt. Wenn der Wert überschritten wird, wird das gesamte Array im Speicher neu angelegt.
 
Zuletzt bearbeitet:
Vielen Dank, werds gleich Testen!

Sort werd ich auf keinen Fall benutzen, ich speichere einen Stundenplan mit Woche, Wochentag, Gruppe ... und wer will schon Englisch in der ersten Stunde haben ;-)


Ich nehme mal an, es gibt keinen einfachen Befehl um eine 4-Dimensionale ArrayList (oder Array) Beispielsweise nach dem Wort "Englisch" zu durchsuchen?
(mit Arrays.binarySearch() geht's schonmal nicht) ;-)
 
Das klingt so, als ob du eine HTML Seite in Assembler schreiben willst ... :freak:

Java ist eine Objekt-Orientierte Sprache! Also benutze das Konzept bitte auch ;) Ob dein Programm am Ende 20 oder 30kb groß ist, interessiert einen Computer der letzten 15 Jahre herzlich wenig. Genauso, ob es nun 2 oder 4MB mehr RAM braucht.

Im Grunde hast du 4 Objekte:
1. Woche (1-52)
2. Tag (0-31)
3. Stunden (von - bis)
4. Fach

Die verschachtelst du einfach entsprechend. Und fertig, dann muss man sich auch nicht mit so bekloppten Array-Konstruktionen rumschlagen.

Natürlich lässt sich das auch noch anderes Modellieren, z.B. mit einer einzigen Klasse:
Code:
DateTime start;
Duration duration;
String subject;
und dann hast du einfach eine List von dieser Klasse. Oder ein Set, wenn du Lust hast noch equals und hashcode zu implementieren ;)


EDIT: Wenn du die Array-Konstruktion von oben durchsuchen willst, musst du natürlich auf den Objekten selbst suchen und nicht auf dem äußersten Array. Also in etwa so:
Code:
int index = Arrays.binarySearch(myArray[5][9][2], "Englisch")
myArray[5][9][2][index]; // <- Ergebnis
Dann wird genau dieses eine Array durchsucht, aber im Endeffekt musst du für "5", "9" und "2" alle möglichen Zahlen Kombinationen einsetzen, um deine Ergebnisse zu erhalten.
 
Zuletzt bearbeitet:
benneque schrieb:
EDIT: Wenn du die Array-Konstruktion von oben durchsuchen willst, musst du natürlich auf den Objekten selbst suchen und nicht auf dem äußersten Array. Also in etwa so:
Code:
int index = Arrays.binarySearch(myArray[5][9][2], "Englisch")
myArray[5][9][2][index]; // <- Ergebnis
Dann wird genau dieses eine Array durchsucht, aber im Endeffekt musst du für "5", "9" und "2" alle möglichen Zahlen Kombinationen einsetzen, um deine Ergebnisse zu erhalten.

Soweit bin ich auch schon ;-) wird halt viel Text

Zum Rest kann ich nur sagen, dass ich schon seit letzter Woche über einen möglichen Algorithmus für mein Vorhaben überlege.
Dabei war ein Objekt wo ich alles reinpacke schon eine "Ansatzidee", die ich mir niedergeschrieben hab, ist also in Überlegung ob ichs so mach.

Ich danke euch auf jeden Fall!
 
Wenn du das Teil wirklich benutzen willst... wo bekommt dein Programm seine Daten her? Datenbank? Dann würde ich die zum Suchen benutzen.
 
Kenn ich zu gut ;) ... ich hab die letzten Monate ca. 60 verschiedene CSV Dateien, mit einem Gesamtvolumen von ca. 120MB auslesen dürfen. Im Prinzip waren es nur kommaseparierte Strings, allerdings durfte ich darin dann die Semantik suchen. Finde mal heraus welcher Geldbetrag gemeint ist, wenn in einer Spalte folgende Einträge stehen "50,00", "50.00", "50€", "50,-", "fünfzig EUR", dann noch mit beliebigen Leerzeichen, Rechtschreibfehlern, etc. :D


Zurück zum Thema. Kannst du das Format der CSV Datei hier posten? Und dazu noch die Suchanfragen (am besten als normaler deutscher Text), die du auf den Daten ausführen willst. Dann lässt sich auch einfach das richtige Format finden.
 
Bin mir zwar nicht sicher wohin das führt, aber:

meine CSV:
Code:
Mo1;ever;ever;PP;PP;PP;PP;space;UGdW;UGdW;UGdW;UGdW
Mo1;ever;ever;E;E;E;E;space;E;E;E;E
Di1;PP;PP;PP;PP;ever;ever;space;ever;ever;space;space
Di1;PP;PP;PP;PP;ever;ever;space;ever;ever;space;space
Mi1;ever;ever;ever;ever;ever;ever;space;UGdI;UGdI;UGdI;UGdI
Mi1;ever;ever;ever;ever;ever;ever;space;PP;PP;PP;PP
Do1;space;space;space;space;ever;ever;space;ever;ever;space;space
Do1;space;space;space;space;ever;ever;space;ever;ever;space;space
Fr1;ever;ever;UGdW;UGdW;UGdW;UGdW;space;space;space;space;space
Fr1;ever;ever;space;space;space;space;space;space;space;space;space
Mo2;ever;ever;PP;PP;PP;PP;space;UGdW;UGdW;UGdW;UGdW
Mo2;ever;ever;E;E;E;E;space;E;E;E;E
Di2;PP;PP;PP;PP;ever;ever;space;ever;ever;space;space
Di2;space;space;space;space;ever;ever;space;ever;ever;space;space
Mi2;ever;ever;ever;ever;ever;ever;space;UGdI;UGdI;UGdI;UGdI
Mi2;ever;ever;ever;ever;ever;ever;space;space;space;space;space
Do2;space;space;space;space;ever;ever;space;ever;ever;space;space
Do2;space;space;space;space;ever;ever;space;ever;ever;space;space
Fr2;ever;ever;UGdW;UGdW;UGdW;UGdW;space;space;space;space;space
Fr2;ever;ever;PP;PP;PP;PP;space;space;space;space;space

Mein Quellcode zum auslesen: (Isn rechtes durcheinander)
Code:
private String[][][][] readCSV(String sPfad) throws IOException {
		Vector<String[]> stringVektor = new Vector<String[]>();

		String trennzeichen = ";";
		BufferedReader in = new BufferedReader(new FileReader(new File(sPfad)));
		try {

			String readString;
			while ((readString = in.readLine()) != null) {
				stringVektor.add(readString.split(trennzeichen));
			}

		} catch (Exception e) {
			e.printStackTrace();
		} finally {
			in.close();
		}

		// Array-Längen herausfinden

		int iZeilen = 1;

		for (int i = 0; i < stringVektor.size(); i++) {
			if (stringVektor.get(i)[0].substring(0, 2).equals(
					stringVektor.get(i + 1)[0].substring(0, 2))) {
				System.out.println("+1");
				System.out.println(stringVektor.get(i)[0].substring(2, 3));
				System.out.println(stringVektor.get(i + 1)[0].substring(2, 3));
				iZeilen++;
			} else {
				break;
			}

		}

		String[][][][] Fach = new String[stringVektor.size() / 5 / iZeilen][5][iZeilen][stringVektor
				.get(0).length - 1];

		System.out.println("\n\n[" + (stringVektor.size() / 5 / iZeilen)
				+ "][5][" + iZeilen + "][" + (stringVektor.get(0).length - 1)
				+ "]");

		int iZeile = 0;
		int iWoche = -1;
		int iDay = -1;

		for (int i = 0; i < stringVektor.size(); i++) {

			if (stringVektor.get(i)[0].substring(0, 2).equals("Mo")) {
				System.out.println("Montag");

				if (iDay == 0) {
					iZeile++;
				} else {
					iWoche++;
					iZeile = 0;
				}

				iDay = 0;

			} else if (stringVektor.get(i)[0].substring(0, 2).equals("Di")) {
				System.out.println("Dienstag");

				if (iDay == 1) {
					iZeile++;
				} else {
					iZeile = 0;
				}

				iDay = 1;

			} else if (stringVektor.get(i)[0].substring(0, 2).equals("Mi")) {
				System.out.println("Mittwoch");

				if (iDay == 2) {
					iZeile++;
				} else {
					iZeile = 0;
				}

				iDay = 2;
			} else if (stringVektor.get(i)[0].substring(0, 2).equals("Do")) {
				System.out.println("Donnerstag");

				if (iDay == 3) {
					iZeile++;
				} else {
					iZeile = 0;
				}

				iDay = 3;
			} else if (stringVektor.get(i)[0].substring(0, 2).equals("Fr")) {
				System.out.println("Freitag");

				if (iDay == 4) {
					iZeile++;
				} else {
					iZeile = 0;
				}

				iDay = 4;
			} else {
				System.err.println(stringVektor.get(i)[0].substring(1, 2));

				System.err.println("Fehlerhafte Datei");

				// TODO Throw Exception!!!
			}
			for (int x = 1; x < stringVektor.get(i).length; x++) {
				System.out.println("Fach[" + iWoche + "][" + iDay + "]["
						+ iZeile + "][" + (x - 1) + "] "
						+ stringVektor.get(i).length + " "
						+ stringVektor.get(i)[x]);

				Fach[iWoche][iDay][iZeile][x - 1] = stringVektor.get(i)[x];
			}
		}

		System.out.println(Fach[0][0][0][0]);

		return Fach;
	}

Zur Sortierung ist nur die erste Spalte wichtig.

Mo1 steht zum Beispiel für "Montag + Woche 1 + Gruppe 1"

steht danach gleich wieder Mo1 steht das für "Montag + Woche 1 + Gruppe 2"

Rechts sind die Fächer.


Das ist der Studienplan von nem Werksstudenten und ich mache (als Übung) ihm ein Programm, das ihm hilft seine Fächer zu wählen. Er Muss zB. von den 8mal Englisch nur 2 besuchen, das Programm soll dann erkennen, dass er am besten die ersten beiden nimmt, damit er früh heim kommt und nicht Stundenlang in der Uni hocken muss.

"ever" steht für Fächer die er sowieso besuchen muss und "space" ist Freizeit


Mit der kompletten einlese bin ich eig. fertig habs so gespeichert: Fach[Woche][Wochentag][Zeile (0 oder 1)][Spalte]

(Zeile gibt es, da mehrere Fächer parallel laufen können, man kann natürlich nur ein Fach zur glecihen Zeit besuchen, außer man ist Hermine... ^^)


Ich weiß das ist verdammt kompliziert gelöst, aber da es nun Funktioniert rühr ichs nicht mehr an!
 
Okay, dann kann man das natürlich mit einem 4D-Array machen (auch wenn ich 2x 3D sinnvoller fände:
Fach[Woche][Wochentag][Spalte] für Gruppe1
Fach[Woche][Wochentag][Spalte] für Gruppe2
).
Aber das ist eher zweitrangig.

Dann brauchst du auf jeden Fall zunächst noch ein 3D-Array für das Endergebnis:
Fach[Woche][Wochentag][Spalte] für das Endergebnis

Dann sollte dein Algorithmus erstmal alle festen Termine in die Endergebnisliste übertragen:
Also alle "ever" Einträge, die sich in Gruppe 1 und 2 überschneiden

Dann hast du schon mal ein Konstrukt, mit dem man weiterarbeiten kann:
Finde alle Lücken in der Ergebnisliste, also quasi Freistunden zwischen den "ever" Terminen an einem Tag und versuche im Quell-Array Datensätze zu finden, die da reinpassen.
Mit etwas Glück, hast du dann schon mal lückenlose Blöcke.

Dann geht's daran vor und nach diesen Blöcken weitere Termine anzuknüpfen.
Jetzt hängt es natürlich von der Reihenfolge der gelesenen Daten ab, ob das Ergebnis optimal ausfällt oder eher nicht. Also im Prinzip müsste man alle Kombinationsmöglichkeiten ausprobieren und am Ende alle Ergebnislisten vergleichen und herausfinden, wo am wenigsten Lücken auftreten.

Und natürlich musst du die ganze Zeit Buch über die Kurse führen, sodass z.B. am Ende 4x Englisch gewählt wurde und nicht weniger oder öfter.
 
So ähnlich mein Ansatz, das mit dem ever vergleichen ist auch schon mal ein guter Anfang für den ich dir danke.

Ich habe auch schon 2 Methoden geschrieben.

Die Eine soll alle Möglichen Kombinationen herausfinden und diese in einer ArrayListe<String[][][][]> wieder zurückgeben an die...
...Zweite Methode, welche dann überprüft, welche Möglichkeiten dem Benutzerwunsch am ehesten entsprechen.


Dass der ganze Spaß am Ende überprüft werden muss ist mir klar ;-)


Ich hab übrigens keine 2 Arrays gewählt, da es auch mehr als nur 2 parallele Tage geben soll. Für den unwahrscheinlichen Fall, dass jemand anderes mein Programm benutzen will ;-)
Die Zeile kann also auch mal 2 3 oder 4 sein können
 
Oder du machst es ganz stupide. Es sind ja nicht so viele Eingabe-Werte. Du könntest natürlich auch ganz stumpf alle möglichen validen Kombinationen berechnen, dann nach und nach die mit den größten Lücken entfernen und zum Schluss hast du dann 3-4 Ergebnisse (im Optimalfall natürlich nur 1, aber gehen wir mal nicht vom best-case aus) die gleich gut bzw. gleich schlecht sind.
Dann kannst du dem User diese anzeigen und er kann sich dann den Plan auswählen, der am Besten zu ihm passt, weil er (wie ich ;) ) z.B. niemals um halb 7 Morgens aus dem Bett kommt und lieber erst Vorlesungen ab 10 haben will.

Die Methode von oben hat nämlich einen entscheidenden Nachteil: Man berechnet nur 1 Lösung und ich kann dir mit Sicherheit sagen, dass das Ergebnis auch völlig daneben sein kann oder das Programm gar kein Ergebnis findet.

Bsp:
Das Ergebnis ist _fast_ fertig berechnet. Es gibt fehlt noch 1x "Fach A" und 1x "Fach B". "Fach A" ist noch 2x in den Quelldaten: Mo 8-10 und Fr 14-16 Uhr. "Fach B": Mo 8-18 und Di 10-12 (schon belegt). Jetzt stößt das Programm auf "Fach A" und probiert als erstes "Montag 8-10", das passt lückenlos in den aktuellen Plan -> Einfügen. Danach sieht es "Fach B" und kann es nirgends mehr einfügen.

Solch ein Fehler kann an allen möglichen Stellen auftreten und einen korrekten Algorithmus für dieses Problem zu schreiben ist kein Kinderspiel. Deshalb sollte man gleich _alle_ validen Kombinationsmöglichkeiten berechnen und fertig. Da muss man sich keine großartigen Gedanken machen und hat am Ende auf jeden Fall das optimale Ergebnis.


EDIT: Wenn man bei Google nach dem Problem sucht findet man genau das!
"Our current implementation works great, and uses brute force" http://stackoverflow.com/a/210700/1321564

Und die letzte Antwort da, ist natürlich perfekt: Prolog! (Eine Programmiersprache, die genau für solch eine Problemstellung geschaffen wurde) http://stackoverflow.com/a/2920941/1321564

Oder hier: "This problem is NP-Complete! In a nutshell one needs to explore all possible combinations" http://stackoverflow.com/questions/2177836/algorithm-for-creating-a-school-timetable

(die NP-Vollständigkeit musst dir nicht ansehen, ganz ganz ganz einfach ausgedrückt heißt das: Der Algorithmus, um das Problem zu lösen, kann nicht effizient arbeiten, also sollte/muss brute force benutzt werden)


Fazit: Prolog oder Brute-Force! Wobei Prolog natürlich auch nur ein hübscheres Brute-Force ist, aber dann bräuchtest du auch kein Java Programm mehr und müsstest eine neue Sprache lernen ;)
 
Zuletzt bearbeitet:
Zurück
Oben