Porovnání polí a odebrání elementů, které se shodují

Upozornění: Tohle vlákno je hodně staré a informace nemusí být platné pro současné Nette.
warriotox
Člen | 30
+
0
-

Snažím se vypsat rezervace v daném terínu. Jako nejsnaží řešení mě napadlo vytáhnout si z databáze všechny pokoje a jejich postele a udělat z nich pole, které obsahuje element vždy s ID pokoje na prním místě a polem s postelemi na druhém místě. Takže pro příklad pokoje ID 1 se 2 postelemi a pokoje ID 2 s 4 postelemi
to pole vypadá takto:

$poleVsechnyPokoje = [[1[1,2]],[2[1,2,3,4]]]
//spravne s PHP by se to zapasalo takhle?
$poleVsechnyPokoje = array(array(1,array(1,2)),array(2,array(1,2,3,4)));
//?

S tímté polem pak tedy srovnávám rezervace které se konají v daném termínu proměněné na pole kde je vždy element s ID rezervovaného pokoje a na druhém pole s rezervovanou postelí. Takže pro příklad rezervace na pokoj 1 v něm postel číslo 2 by vypadala takto:

$poleRezervace = [1[2]]

Tudíž moje otazká je jak porovnat $poleRezervace s $poleVsechnyPokoje a odebrat z něj obsazené postele pro každý pokoj, tudíž výsledné pole by bylo:

$poleDostupnePokoje [1[1],[2[1,2,3,4]]]

Hádám, že $poleDostupnePokoje = $poleVsechnyPokoje - $poleReervace to nebude… Původně jsem se chtěl zeptat na StackOverflow, ale pak mě napadlo, že jestli na to má Nette i nějaký helper tak bych rád využil i toho..

Editoval warriotox (19. 2. 2016 19:43)

GEpic
Člen | 566
+
0
-

Když jsme u stackoverflow, zkus toto:

http://stackoverflow.com/…sional-array

Editoval GEpic (19. 2. 2016 20:09)

Martk
Člen | 661
+
0
-

Není lepší tohle řešit sql dotazem?

Pravděpodobně hledáš něco jako array diff recursive např. http://php.net/…ray-diff.php#…

Editoval Antik (19. 2. 2016 21:26)

GEpic
Člen | 566
+
0
-

Do budoucna z důvodu rozšiřování a udržování dalších informací ohledně pokojů, jako například cen, vybavení, a podobně bych to také určitě řešil pomocí databáze a k tomu bych si vytvořil 2 entity – RoomBed

EDIT:
Řešení tvého případu může být následující. Schválně se podívej na dumps v Tracy, jak vypadá výsledné pole.
Problém polí je ten, že musí mít jak klíč, tak hodnotu, což může být v tomto případě problém, protože číslo postele (value) 1, má ve skutečnosti index (klíč /key) 0. Přikládám i jak vypadá výsledný dump.

		$poleVsechnyPokoje = array(
			// Pokoj 1 (Key) => Postele (Array)
			1 => array (
				// Postel (Value)
				1, // Bude mít ve finále key / klíč 0 (čili 0 => 1)
				2
			),
			2 => array(
				1,
				2,
				3,
				4
			)
		);

		$poleRezervace = array(
			1 => array(
				2
			)
		);

		// Dump pole před operací
		Debugger::barDump($poleVsechnyPokoje);

		// foreach (<pole> as <key> => <value>
		foreach ($poleRezervace as $pokoj => $postele)
			// foreach (keys of <pole> as <key>)
			foreach(array_keys($postele) as $postel)
				unset($poleVsechnyPokoje[$pokoj][$postel]);

		// Dump pole po operaci
		Debugger::barDump($poleVsechnyPokoje);

DUMP Před:

array (2)
1 => array (2)
	0 => 1
	1 => 2
2 => array (4)
	0 => 1
	1 => 2
	2 => 3
	3 => 4

DUMP Po:

array (2)
1 => array (1)
	1 => 2
2 => array (4)
	0 => 1
	1 => 2
	2 => 3
	3 => 4

Dovysvětlení:

$poleVsechnyPokoje[$pokoj][$postel] // Čili $pole[<klic pokoje>][<klic postele>]

// Jenže my určujeme v poli values, né keys, proto:
array_keys($postele)

Editoval GEpic (19. 2. 2016 21:35)

warriotox
Člen | 30
+
0
-

GEpic napsal(a):
Řešení tvého případu může být následující. Schválně se podívej na dumps v Tracy, jak vypadá výsledné pole.
Problém polí je ten, že musí mít jak klíč, tak hodnotu, což může být v tomto případě problém, protože číslo postele (value) 1, má ve skutečnosti index (klíč /key) 0. Přikládám i jak vypadá výsledný dump.

V první řadě moc díky za odbsáhlou odpověď, už to čtu asi po 30tý a nemůžu pochopit proč tam ve finále zůstane ta postel #2 a ne ta postel #1. Přece shodné je $poleRezervace[1 ⇒ array (2)] s $poleVsechnyPokoje[1 ⇒ array (2)], tak jaktože pak ve výsledku je tohle?

EDIT: Nebo to je ten problém který popisuješ teda?

EDIT 2: a nemeli by ty pole byt nadefinovany takhle:

//proměnná je pole kde na indexu 0 je pole
$poleVsechnyPokoje = array(	0=>array(
									//kde na indexu 0 je hodnota 1 (id pokoje)
									0=>1,
									//a na indexu 1 je pole
									1=>array(
											//kde na indexu 0 je hodnota 1 (radove cislo postele)
											0=>1,
											//kde na indexu 1 je hodnota 2 (dalsi postel..)
											1=>2)),
							//na indexu 1 je pole... znovu jako vyse
							1=>array(
									0=>2,
									1=>array(
											0=>1,
											1=>2,
											2=>3,
											3=>4)));

$poleRezervace = 	array(	0=>array(
									0=>1,
									1=>array(0=>2)));
//pro lepsi priklad zamenim ty ciselne hodnoty za text
//proměnná je pole kde na indexu 0 je pole
$poleVsechnyPokoje = array(	0=>array(
									//kde na indexu 0 je hodnota 'Luxusni Pokoj' (nazev pokoje)
									0=>'Luxusni Pokoj',
									//a na indexu 1 je pole
									1=>array(
											//kde na indexu 0 je hodnota 'xx1' (kod postele)
											0=>'xx1',
											//kde na indexu 1 je hodnota 'xx2' (kod postele)
											1=>'xx2')),
							//na indexu 1 je pole... stejny zpusob jako vyse...
							1=>array(
									0=>'Levny Pokoj',
									1=>array(
											0=>'zz1',
											1=>'zz2',
											2=>'zz3',
											3=>'zz4')));

$poleRezervace = 	array(	0=>array(
									0=>'Luxusni Pokoj',
									1=>array(0=>'xx2')));

\--
Tudiz pak co se shoduje HODNOTA je $poleRezervace[0][1][0] ⇒ 2 ci text ‚xx2‘ s $poleVsechnyPokoje[0][1][1] ⇒ 2 ci text ‚xx2‘. Takze element na pozici[0][1][1] se Vymaze z $poleVsechnyPokoje a vsechny ostatni zustatnou. Takze ja pak muzu vypsat vsechny ID pokoju a jednotlivy postele a jenom ta postel cislo 2 z prvniho pokoje se nevypise, coz je tak jak by to melo fungovat. Ale ty pises ze vysledek je odstraneni ty postele cislo jedna a zustane 2ka, furt mi to nejde na rozum

Editoval warriotox (19. 2. 2016 23:44)

Martk
Člen | 661
+
0
-

@warriotox Tady je problém, že se klíče nemusí shodovat a ten kód od GEpic předpokládá, že budou stejné (sám to píše v odpovědi).

Tady je kód, který na to nehledí:

foreach ($poleVsechnyPokoje as $klicPokoje => $pole) {
	$nalezeno = NULL;
	foreach ($poleRezervace as $klic => $poleRez) {
		if ($poleRez[0] === $pole[0]) {
			$nalezeno = $poleRez[1];
			unset($poleRezervace[$klic]); // Již nepotřebujeme, v dalších iteracích se nebude zbytečně prohledávat
			break;
		}
	}
	if (!$nalezeno) {
		continue;
	}

	foreach ($pole[1] as $key => $hodnota) {
		$klicPostele = array_search($hodnota, $nalezeno);
		if ($klicPostele !== FALSE) {
			unset($poleVsechnyPokoje[$klicPokoje][1][$key]);
		}
	}

	if (!$poleVsechnyPokoje[$klicPokoje][1]) {
		unset($poleVsechnyPokoje[$klicPokoje]);
	}
}

Editoval Antik (20. 2. 2016 10:50)

warriotox
Člen | 30
+
0
-

Antik napsal(a):

@warriotox Tady je problém, že se klíče nemusí shodovat a ten kód od GEpic předpokládá, že budou stejné (sám to píše v odpovědi).

Tady je kód, který na to nehledí:

Supr díky moc, já sem to ještě než jsem šel spát hodil na StackOverflow ale s tím uspořádáním polí jak jsem navrhoval já, a tam navrhli rešení níže. Každopádně jsem si pak uvědomil, že jsem nebral vůbec v potaz dny o kterých by měli být pokoje a jejich postele volné a napsal sem nový mnohem obsáhlejší post, kde se snažím přijít na to jak to vyřešit už na úrovni databáze, tak jak jsi ostatně sám navrhoval hned v prví odpovědi. Pokud umíš anglicky tak tady je odkaz, jinak zatím moc děkuji za rady, jestli mi to na Stacku někdo pomůže vyřešit tak sem pak doplním řešení.

//reseni pro pripad usporadani poli jak jsem navrhoval v mem komentari z 21:40
foreach ($all as &$room) {
    foreach ($reserved as $r) {
        if ($room[0] == $r[0]) { // same types of room
            foreach ($room[1] as $i => $code) {
                if (in_array($code, $r[1])) {
                    unset($room[1][$i]);
                }
            }
        }
    }
    $room[1] = array_values($room[1]); // Reset array indexes
}

Editoval warriotox (20. 2. 2016 11:37)

GEpic
Člen | 566
+
0
-

warriotox napsal(a):

Antik napsal(a):

@warriotox Tady je problém, že se klíče nemusí shodovat a ten kód od GEpic předpokládá, že budou stejné (sám to píše v odpovědi).

Tady je kód, který na to nehledí:

Supr díky moc, já sem to ještě než jsem šel spát hodil na StackOverflow ale s tím uspořádáním polí jak jsem navrhoval já, a tam navrhli rešení níže. Každopádně jsem si pak uvědomil, že jsem nebral vůbec v potaz dny o kterých by měli být pokoje a jejich postele volné a napsal sem nový mnohem obsáhlejší post, kde se snažím přijít na to jak to vyřešit už na úrovni databáze, tak jak jsi ostatně sám navrhoval hned v prví odpovědi. Pokud umíš anglicky tak tady je odkaz, jinak zatím moc děkuji za rady, jestli mi to na Stacku někdo pomůže vyřešit tak sem pak doplním řešení.

//reseni pro pripad usporadani poli jak jsem navrhoval v mem komentari z 21:40
foreach ($all as &$room) {
    foreach ($reserved as $r) {
        if ($room[0] == $r[0]) { // same types of room
            foreach ($room[1] as $i => $code) {
                if (in_array($code, $r[1])) {
                    unset($room[1][$i]);
                }
            }
        }
    }
    $room[1] = array_values($room[1]); // Reset array indexes
}

Pokud můžu poradit, tak toto řeš už na našem fóru. Přeci jen pro práci s databází jsou v Nette šikovné funkce a navrhnuté řešením na StackOverflow si zbytečně zkomplikuješ život.

EDIT: Podobnou aplikaci jsem psal také, univerzálně na jakékoliv možné rezervace, v produkci je zatím upravená verze pro tenisové kurty, můžeš mrknout zde http://scpanamera.cz/ . Kdyby tě něco zajímalo, klidně napiš soukromou zprávu. Bez přihlášení vidíš obsazené rezervace, po přihlášení je informací víc, ale není potřeba.

Editoval GEpic (21. 2. 2016 4:39)