I have situation that I have to compare dynamic arrays, and get count of arrays with similar values for first four keys only. For ex:
我有这种情况,我必须比较动态数组,并获得前四个键具有相似值的数组的计数。例如:
Array[0]
(
[item] => 1
[size] => 1
[pair] => 1
[pay] => 1
[name] =>
[msg] =>
[email] =>
[b19e19b13682bcfef93651c86f9ad9e6] => eih6j74035oj17bvnses32km23
)
Array[1]
(
[item] => 1
[size] => 2
[pair] => 1
[pay] => 1
[name] =>
[msg] =>
[email] =>
[b19e19b13682bcfef93651c86f9ad9e6] => eih6j74035oj17bvnses32km23
)
Array[2]
(
[item] => 1
[size] => 2
[pair] => 2
[pay] => 2
[name] =>
[msg] =>
[email] =>
[b19e19b13682bcfef93651c86f9ad9e6] => eih6j74035oj17bvnses32km23
)
Array[3]
(
[item] => 1
[size] => 1
[pair] => 1
[pay] => 1
[name] =>
[msg] =>
[email] =>
[b19e19b13682bcfef93651c86f9ad9e6] => eih6j74035oj17bvnses32km23
)
I have the above set of arrays which has 1st and last iterations has similar values(for 1st four keys). For this I have to derive something like (0,3),(1),(2). is there any solution for this?
我有上面的数组,其中第一次和最后一次迭代具有相似的值(对于前四个键)。为此我必须得到像(0,3),(1),(2)这样的东西。这有什么解决方案吗?
3 个解决方案
#1
0
this should works fine:
这应该工作正常:
put your arrays in one array as I did in $arrays
, then:
像在$数组中那样将数组放在一个数组中,然后:
<?php
$arrays = [
array('a'=>1, 'b'=>2, 'c'=>3, 'd'=>4),
array('a'=>1, 'b'=>2, 'c'=>3, 'd'=>4),
array('a'=>1, 'b'=>2, 'c'=>3, 'd'=>4),
array('a'=>1, 'b'=>2, 'c'=>4, 'd'=>3),
];
$result = [];
//get the keys of a sub-array that is inside $arrays, to be used later
$keys = array_keys($arrays[0]);
for($i=0; $i < sizeof($arrays); $i++){
$sa = array(); // to store similar arrays indexes
for($k=$i+1; $k < sizeof($arrays); $k++){
$similar = false;
//compare the values of keys in the two arrays. Just compare the first 4 keys (as the user's desire)
for($j=0; $j < 4; $j++){
//check if the values are similar, if they are, assign $similar to true, and assign $j=3 to end the loop, (a bit of laziness here)
($similar = $arrays[$i][$keys[$j]] == $arrays[$k][$keys[$j]] ? true : false) ? null : ($j=3);
}
// check if the key (which represents an index in $arrays) is in $sa or not, if not, push it.
$similar ? (in_array($i, $sa) ? null : array_push($sa, $i) && in_array($k, $sa) ? null : array_push($sa, $k)) : null;
//if $similar is true, make $i jumps to the $k index (saving time)
$similar ? $i=$k : null;
}
//if $sa not empty, push it to $result
empty($sa) ? null : ($result[] = $sa);
}
/*
// at this stage, $result includes all the similar arrays
// so we need another loop to push the unique arrays to $result
// just check if an index of $arrays is in an sub-array of $result, if not, push it as an array of one record
*/
for($j=0; $j < sizeof($arrays); $j++){
$f = false;
for($i=0; $i < sizeof($result); $i++){
in_array($j, $result[$i]) ? $f = true : null;
}
if(!$f){
$sa = array();
array_push($sa, $j);
array_push($result, $sa);
}
}
finally, $result is an array of arrays, each sub-array values represents an index of $arrays if the result output is :
最后,$ result是一个数组数组,如果结果输出为:每个子数组值代表$ arrays的索引:
array(2) {
[0]=> array(3) {
[0]=> int(0)
[1]=> int(1)
[2]=> int(2)
},
[1]=> array(1) {
[0]=> int(3)
}
}
this means that $arrays has two groups of sub-arrays, where $arrays[0], $arrays[1], and $arrays[2] are similar (group 1), then $arrays[3] is unique (group 2)
这意味着$ arrays有两组子数组,其中$ arrays [0],$ arrays [1]和$ arrays [2]相似(组1),然后$ arrays [3]是唯一的(组2) )
N.B: I would appreciate if anyone could optimize my answer.
N.B:如果有人能够优化我的答案,我将不胜感激。
#2
0
Personally, i prefer OOP approach : more clean, reusable...
就个人而言,我更喜欢OOP方法:更干净,可重复使用......
USAGE
用法
$o = new SOF_ArrayComapare($yourInputArray, array('item', 'size', 'pair', 'pay', 'name'));
$arraysEqual = $o->getEqualArrays();
print $o->toString();
CLASS DEFINITION
类别定义
class SOF_ArrayComapare {
private $_keysToMatch = array();
private $_array = array();
public function __construct($array, $keysToMatch) {
$this->_array = $array;
$this->_keysToMatch = $keysToMatch;
}
private $_equalArrays = array();
private $_indexToEscape = array();
public function getEqualArrays() {
$size = count($this->_array);
for ($i=0 ; $i<$size ; $i++) {
if (in_array($i, $this->_indexToEscape)) continue;
else $this->_indexToEscape[] = $i;
$this->_equalArrays[$i][] = $i;
for ($j=($i+1) ; $j<$size ; $j++) {
if (in_array($j, $this->_indexToEscape)) continue;
if ($this->areEquals($this->_array[$i], $this->_array[$j])) {
$this->_indexToEscape[] = $j;
$this->_equalArrays[$i][] = $j;
}
}
}
return $this->_equalArrays;
}
private function areEquals($a1, $a2) {
foreach($this->_keysToMatch as $key) {
if(
!isset($a1[$key]) ||
!isset($a2[$key]) ||
$a1[$key] !== $a2[$key]
) {
return FALSE;
}
}
return TRUE;
}
public function toString($htmlFormat = TRUE) {
$newLine = ($htmlFormat === TRUE) ? '<br />' : "\n";
$report = "These arrays are equals: " . $newLine;
foreach($this->_equalArrays as $array) {
$report .= '(' . implode(',', $array) . ')' . $newLine;
}
return $report;
}
}
#3
0
I'll explain this at the end, but the code is pretty self explanatory:
我将在最后解释这一点,但代码是非常自我解释的:
function getDuplicatesArray()
{
$foundIndexes = array();
$arraysCount = count(Array);
$resultArray = array();
// $i is current index
// $j is compared index
for ($i = 0; i < $arraysCount; i++)
{
if (in_array($i, $foundIndexes))
continue;
$currentResultArray = array($i);
for ($j = $i+1; $j<$arraysCount; $j++)
{
if (in_array($j, $foundIndexes))
continue;
if(areFirstValsSame($i,$j))
{
$currentResultArray[] = $j;
if (count($currentResultArray) == 2) // first j for this i
foundIndexes[] = $i;
foundIndexes[] = $j;
}
}
$resultArray[] = $currentResultArray;
}//.. for i
}//.. getDuplicatesArray
function areFirstValsSame($index1, $index2){
$toCompare = 4;
for ($i=0; i<$toCompare; i++)
if (Array($index1, i) != Array($index2, i)
return false;
return true;
}
A "found" array saves all indexes with duplicates.
“找到”数组会保存所有具有重复项的索引。
When a duplicate is found the Array's index is added to the "found".
找到重复项后,Array的索引将添加到“found”中。
A current-found saves all indexes of duplicate Arrays being compared to the current Array.
current-found保存与当前Array比较的重复Arrays的所有索引。
Then before testing the next index, check if it was found before, and if so skip it.
然后在测试下一个索引之前,检查之前是否找到它,如果是,则跳过它。
Once an index has been compared (whether finding a duplicate or not) its current-found is added to the result.
一旦比较了一个索引(无论是否找到重复索引),就会将其当前找到的索引添加到结果中。
If all four Arrays were the same you would get: (0,1,2,3)
and if the first and third were duplicate and the second and fourth you would get: (0,2),(1,3) etc.
如果所有四个阵列都是相同的,你会得到:(0,1,2,3)如果第一个和第三个是重复的,第二个和第四个是你得到的:(0,2),(1,3)等。
You would not be checking a duplicate twice. But you would still need to re-read the values of those Arrays that were not found duplicate to the indices checked till now.
你不会两次检查重复。但是你仍然需要重新读取那些未被发现重复到目前检查的索引的数组的值。
That could be optimized by recursion, but would take up more memory, and with this small amount of arrays, it would not even be noticeable.
这可以通过递归来优化,但会占用更多的内存,并且使用这么少的数组,它甚至都不会引人注意。
#1
0
this should works fine:
这应该工作正常:
put your arrays in one array as I did in $arrays
, then:
像在$数组中那样将数组放在一个数组中,然后:
<?php
$arrays = [
array('a'=>1, 'b'=>2, 'c'=>3, 'd'=>4),
array('a'=>1, 'b'=>2, 'c'=>3, 'd'=>4),
array('a'=>1, 'b'=>2, 'c'=>3, 'd'=>4),
array('a'=>1, 'b'=>2, 'c'=>4, 'd'=>3),
];
$result = [];
//get the keys of a sub-array that is inside $arrays, to be used later
$keys = array_keys($arrays[0]);
for($i=0; $i < sizeof($arrays); $i++){
$sa = array(); // to store similar arrays indexes
for($k=$i+1; $k < sizeof($arrays); $k++){
$similar = false;
//compare the values of keys in the two arrays. Just compare the first 4 keys (as the user's desire)
for($j=0; $j < 4; $j++){
//check if the values are similar, if they are, assign $similar to true, and assign $j=3 to end the loop, (a bit of laziness here)
($similar = $arrays[$i][$keys[$j]] == $arrays[$k][$keys[$j]] ? true : false) ? null : ($j=3);
}
// check if the key (which represents an index in $arrays) is in $sa or not, if not, push it.
$similar ? (in_array($i, $sa) ? null : array_push($sa, $i) && in_array($k, $sa) ? null : array_push($sa, $k)) : null;
//if $similar is true, make $i jumps to the $k index (saving time)
$similar ? $i=$k : null;
}
//if $sa not empty, push it to $result
empty($sa) ? null : ($result[] = $sa);
}
/*
// at this stage, $result includes all the similar arrays
// so we need another loop to push the unique arrays to $result
// just check if an index of $arrays is in an sub-array of $result, if not, push it as an array of one record
*/
for($j=0; $j < sizeof($arrays); $j++){
$f = false;
for($i=0; $i < sizeof($result); $i++){
in_array($j, $result[$i]) ? $f = true : null;
}
if(!$f){
$sa = array();
array_push($sa, $j);
array_push($result, $sa);
}
}
finally, $result is an array of arrays, each sub-array values represents an index of $arrays if the result output is :
最后,$ result是一个数组数组,如果结果输出为:每个子数组值代表$ arrays的索引:
array(2) {
[0]=> array(3) {
[0]=> int(0)
[1]=> int(1)
[2]=> int(2)
},
[1]=> array(1) {
[0]=> int(3)
}
}
this means that $arrays has two groups of sub-arrays, where $arrays[0], $arrays[1], and $arrays[2] are similar (group 1), then $arrays[3] is unique (group 2)
这意味着$ arrays有两组子数组,其中$ arrays [0],$ arrays [1]和$ arrays [2]相似(组1),然后$ arrays [3]是唯一的(组2) )
N.B: I would appreciate if anyone could optimize my answer.
N.B:如果有人能够优化我的答案,我将不胜感激。
#2
0
Personally, i prefer OOP approach : more clean, reusable...
就个人而言,我更喜欢OOP方法:更干净,可重复使用......
USAGE
用法
$o = new SOF_ArrayComapare($yourInputArray, array('item', 'size', 'pair', 'pay', 'name'));
$arraysEqual = $o->getEqualArrays();
print $o->toString();
CLASS DEFINITION
类别定义
class SOF_ArrayComapare {
private $_keysToMatch = array();
private $_array = array();
public function __construct($array, $keysToMatch) {
$this->_array = $array;
$this->_keysToMatch = $keysToMatch;
}
private $_equalArrays = array();
private $_indexToEscape = array();
public function getEqualArrays() {
$size = count($this->_array);
for ($i=0 ; $i<$size ; $i++) {
if (in_array($i, $this->_indexToEscape)) continue;
else $this->_indexToEscape[] = $i;
$this->_equalArrays[$i][] = $i;
for ($j=($i+1) ; $j<$size ; $j++) {
if (in_array($j, $this->_indexToEscape)) continue;
if ($this->areEquals($this->_array[$i], $this->_array[$j])) {
$this->_indexToEscape[] = $j;
$this->_equalArrays[$i][] = $j;
}
}
}
return $this->_equalArrays;
}
private function areEquals($a1, $a2) {
foreach($this->_keysToMatch as $key) {
if(
!isset($a1[$key]) ||
!isset($a2[$key]) ||
$a1[$key] !== $a2[$key]
) {
return FALSE;
}
}
return TRUE;
}
public function toString($htmlFormat = TRUE) {
$newLine = ($htmlFormat === TRUE) ? '<br />' : "\n";
$report = "These arrays are equals: " . $newLine;
foreach($this->_equalArrays as $array) {
$report .= '(' . implode(',', $array) . ')' . $newLine;
}
return $report;
}
}
#3
0
I'll explain this at the end, but the code is pretty self explanatory:
我将在最后解释这一点,但代码是非常自我解释的:
function getDuplicatesArray()
{
$foundIndexes = array();
$arraysCount = count(Array);
$resultArray = array();
// $i is current index
// $j is compared index
for ($i = 0; i < $arraysCount; i++)
{
if (in_array($i, $foundIndexes))
continue;
$currentResultArray = array($i);
for ($j = $i+1; $j<$arraysCount; $j++)
{
if (in_array($j, $foundIndexes))
continue;
if(areFirstValsSame($i,$j))
{
$currentResultArray[] = $j;
if (count($currentResultArray) == 2) // first j for this i
foundIndexes[] = $i;
foundIndexes[] = $j;
}
}
$resultArray[] = $currentResultArray;
}//.. for i
}//.. getDuplicatesArray
function areFirstValsSame($index1, $index2){
$toCompare = 4;
for ($i=0; i<$toCompare; i++)
if (Array($index1, i) != Array($index2, i)
return false;
return true;
}
A "found" array saves all indexes with duplicates.
“找到”数组会保存所有具有重复项的索引。
When a duplicate is found the Array's index is added to the "found".
找到重复项后,Array的索引将添加到“found”中。
A current-found saves all indexes of duplicate Arrays being compared to the current Array.
current-found保存与当前Array比较的重复Arrays的所有索引。
Then before testing the next index, check if it was found before, and if so skip it.
然后在测试下一个索引之前,检查之前是否找到它,如果是,则跳过它。
Once an index has been compared (whether finding a duplicate or not) its current-found is added to the result.
一旦比较了一个索引(无论是否找到重复索引),就会将其当前找到的索引添加到结果中。
If all four Arrays were the same you would get: (0,1,2,3)
and if the first and third were duplicate and the second and fourth you would get: (0,2),(1,3) etc.
如果所有四个阵列都是相同的,你会得到:(0,1,2,3)如果第一个和第三个是重复的,第二个和第四个是你得到的:(0,2),(1,3)等。
You would not be checking a duplicate twice. But you would still need to re-read the values of those Arrays that were not found duplicate to the indices checked till now.
你不会两次检查重复。但是你仍然需要重新读取那些未被发现重复到目前检查的索引的数组的值。
That could be optimized by recursion, but would take up more memory, and with this small amount of arrays, it would not even be noticeable.
这可以通过递归来优化,但会占用更多的内存,并且使用这么少的数组,它甚至都不会引人注意。