I have this numeric multidimensional array in php. It's Playfair matrix and I want to get the keys of a letter from the matrix.
Let's say I have the letter "P", which is on the third row(0 to 4) and second column(0 to 4). I have tried several things array_keys(not working as I want it to), functions to get the key of the first level of the array, making the array one dimensional and doing some magic tricks...Nothing works and I would like some help.
This is the function that gets the keys of the first level:
function array_search2($needle, $haystack){
$l = count($haystack);
for ($i=0; $i < $l; $i++) {
if (in_array($needle, $haystack[$i])) return $i;
}
return false;
}
I want to have this array with letters, to get two letters from it, to get these two letters their coordinates(from the PLayfair matrix) and to comprate their rows/columns.
Thank you and I'll post any code that is needed.
Edit : I'm posting all I have:
$keyword = str_replace(' ','', $_POST['keyword']);
$plaintext = str_replace(' ','', $_POST['plaintext']);
$key = str_split($keyword); //string to array
$plain = str_split($plaintext); //string to array
$alphabet = array(
0 => 'a', 1 => 'b', 2 => 'c', 3 => 'd', 4 => 'e', 5 => 'f',
6 => 'g', 7=> 'h', 8 => 'i', 9 => 'j', 10 => 'k', 11 => 'l',
12 => 'm', 13 => 'n', 14 => 'o', 15 => 'p', 16 => 'q', 17 => 'r',
18 => 's', 19 => 't', 20 => 'u', 21 => 'v', 22 => 'w', 23 => 'x',
24 => 'y');
for ($i=0; $i < count($key); $i++) {
for ($j=0; $j < count($alphabet) ; $j++) {
if ($keyword[$i] == $alphabet[$j]) {
unset($alphabet[$j]);
}
}
}
$keywordFilpped = array_flip($key);
$alphabetFlipped = array_flip($alphabet);
$mergedFlipped = $keywordFilpped + $alphabetFlipped;
$i = 0;
foreach ($mergedFlipped as $key => $value) {
$mergedFlipped[$key] = $i;
$i++;
}
$merged = array_flip($mergedFlipped);
$index = 0;
for ($i=0; $i < 5; $i++) {
for ($j=0; $j < 5; $j++) {
$matrix[$i][$j] = $merged[$index];
$index++;
}
}
echo "PLAYFAIR MATRIX:<br>";
for ($i=0; $i < 5; $i++) {
for ($j=0; $j < 5; $j++) {
echo $matrix[$i][$j];
}
echo "<br>";
}
if you have a matrix should check with 2 for like following code:
for($i = 1; $i <= 11; $i++)
{
for($j = 1; $j <= 11; $j++)
{
if($array[$i][$j] == 'p') echo "row=$i and col = $j";
}
}
in the above example i check all rows and rows cols
use from this function
function array_search2($needle, $haystack){
$i = 0;
foreach($haystack as $key => $value)
{
$j = 0;
foreach($value as $key2 => $value2)
{
if($value2 == $needle)
return array($i, $j);
$j++;
}
$i++;
}
return false;
}
this function will return an array contain row and col of found status or false;
i tested with following data:
$array = array( 0 => array(0 => 'a', 1=> 'b'), 1 => array(0 => 'c', 1=> 'd'));
print_r(array_search2('d', $array));
// out put Array ( [0] => 1 [1] => 1 )
I've improved your function, which will return keys if match found, irrespective of depth, See example below:
function getArrayKeys($needle, $haystack, $depth = 0) {
$keys = array();
foreach($haystack as $key => $value) {
if(is_array($value)){
$result = getArrayKeys($needle, $value, $depth + 1);
if(!empty($result) || $result === 0) {
if (is_array($result)) {
$keys = array_merge($keys, $result);
} else {
$keys[] = $result;
}
$keys[] = $key;
}
if(!empty($keys) && $depth > 0)
return $keys;
} elseif($value == $needle) {
return $key;
}
}
return !empty($keys) ? array_reverse($keys) : false;
}
$arr = array(
array('A', 'B', 'C'),
array('D', 'F', 'E'),
array('Z', 'Y', 'X'),
array('f' => '44', 'g' => array('99'))
);
$keys = getArrayKeys('99', $arr);
Output:
Array
(
[0] => 3
[1] => g
[2] => 0
)
See it running: https://eval.in/571698
Related
I have an array like :
Array
(
[0] => a
[1] => b
[2] => c
[3] => d
[4] => e
[5] => f
[6] => g
[7] => h
)
And I want add semicolon(;) every 3 index value and it's read from end of array that result is string like "ab;cde;fgh";
Here's a fun, and kind of obnoxious, one-liner:
$str = ltrim(strrev(chunk_split(implode(array_reverse($arr)), 3, ';')), ';');
Example:
$arr = array('a', 'b', 'c', 'd', 'e', 'f', 'g', 'h');
$str = ltrim(strrev(chunk_split(implode(array_reverse($arr)), 3, ';')), ';');
echo $str; //ab;cde;fgh
// More sample output based on different input arrays:
$arr = array('a', 'b', 'c', 'd', 'e'); //ab;cde
$arr = array('a', 'b', 'c', 'd', 'e', 'f'); //abc;def
$arr = array('a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k'); //ab;cde;fgh;ijk
See demo
Its an odd way, but since you want it reversed you may need to use some function here:
$array = array('a', 'b', 'c', 'd', 'e', 'f', 'g', 'h');
$array = array_reverse($array); // reverse it
$array = array_chunk($array, 3); // cut by threes
$string = '';
foreach ($array as $value) {
$string .= implode($value); // glue them
if(count($value) == 3) { // if still three, add a semi
$string .= ';';
}
}
$string = strrev($string); // then reverse them again
echo $string; // ab;cde;fgh
This works... there's a couple different ways to do this. This was the quickest way off the top of my head without using a second array.
$vars = array("a","b","c","d","e","f","g","h");
print_r(insert_char($vars));
function insert_char($Array, $Delimeter=";", $Count=3) {
for ($i = sizeOf($Array) - $Count; $i > 0; $i -= $Count)
array_splice($Array, $i, 0, $Delimeter);
return implode($Array);
}
Result
ab;cde;fgh
Here's my solution, although it feels inefficient it is pretty clear:
<?php
$myarr=Array('a','b','c','d','e','f','g','h');
$newarr=Array();
$arrsize = sizeof($myarr);
for ($x = 0, $i = 0; $x < $arrsize; $x++, $i++) {
$newarr[$i] = $myarr[$arrsize - $x - 1];
if (($arrsize - $x) % 3 == 0) {
$i++;
$newarr[$i] = ";";
}
}
$newarr = array_reverse($newarr);
print_r($newarr);
?>
Just traversing it from backward and joining the string in reverse too gives that result.
$vars = array("a","b","c","d","e","f","g");
$c = 0; $s = "";
for ($i = sizeof($vars)-1; $i >= 0; $i--)
{
$c++;
$s = $vars[$i].$s;
if ($c == 3) { $c = 0; $s = ";".$s; }
}
echo $s;
EDIT: making it clear that I need it for multidimensional arrays (at any depth level)
I need to cut down the size of an array to get only a portion of it, but this needs to be done recursively. For example, take the following case:
$a = array(
'a',
'b' => array(
'x' => array(
'aleph',
'bet'
),
'y'),
'c',
'd',
'e'
);
what I need is that after copying only 4 elements I'll get the following resulted array:
$a = array(
'a',
'b' => array('x' => array(
'aleph'
),
),
);
and not...
$a = array(
'a',
'b' => array('x' => array(
'aleph',
'bet'
),
'y'),
'c',
'd',
);
How do I achieve this?
Thanks!
You can try **Note : dual-dimensional
$a = array("a","b" => array('x','y'),"c","d","e");
$new = __cut($a);
function __cut($array, $max = 4) {
$total = 0;
$new = array();
foreach ( $array as $key => $value ) {
if (is_array($value)) {
$total ++;
$diff = $max - $total;
$slice = array_slice($value, 0, $diff);
$total += count($slice);
$new[$key] = $slice;
} else {
$total ++;
$new[$key] = $value;
}
if ($total >= $max)
break;
}
return $new;
}
var_dump($new);
Output
array
0 => string 'a' (length=1)
'b' =>
array
0 => string 'x' (length=1)
1 => string 'y' (length=1)
function arrayTrim($array, $size, $finalArray = null){
global $count;
foreach ($array AS $key => $val){
if($size == $count)
return $finalArray;
$count++;
if(is_array($val)){
$finalArray[$key] = array();
$finalArray[$key] = arrayTrim ($val, $size, $finalArray[$key]);
}
else
$finalArray[$key] = $val;
}
return $finalArray;
}
$a = array( "a"=> array('xa', 'ya'), "b" => array('x', 'y'), "c", "d", "e" );
print_r(arrayTrim($a, 4));
should work fine
Consider the following array as input:
$input = array('A', 'B', 'C', 'D');
I'm looking for a way to make loop though this array, writing down every possible pair of two values. In this example: AB AC AD BC BD CD. Please not that BA doesn't count as a pair, since AB is already mentioned:
$output = array(
'A' => 'B',
'A' => 'C',
'A' => 'D',
'B' => 'C',
'B' => 'D'
);
Any input on how to get this started is appreciated!
$output=array();
for ($i=0;$i<sizeof($input);$i++) {
$k=$input[$i];
for ($j=$i+1;$j<sizeof($input);$j++) {
$v=$input[$j];
$output[]=array($k=>$v);
}
}
Edit
As of your comment, the restructured output
$output=array();
//See below
for ($i=0;$i<sizeof($input);$i++) {
$k=$input[$i];
$v=array();
for ($j=$i+1;$j<sizeof($input);$j++) {
$v[]=$input[$j];
}
$output[]=array($k=>$v);
}
This will give you 'D'=>Array() as a last row, if you don't want hti you have to change
for ($i=0;$i<sizeof($input);$i++) {
to
for ($i=0;$i<sizeof($input)-1;$i++) {
something like this maybe;
$input = array('A', 'B', 'C', 'D');
$input_copy = $input;
$output = array();
$i = 0;
foreach($input as $val) {
$j = 0;
foreach($input_copy as $cval) {
if($j < $i) break;
$output[] = array($val => $cval);
$j++;
}
$i++;
}
$output = array(
0 => array('A' => 'A'),
1 => array('A' => 'B'),
2 => array('A' => 'C'),
...
);
Note that your output array is impossible, as the key is overwritten each time
This won't be possible in PHP, as PHP array can have only unique keys.
You can get output as
$output = array(
'A' => array('B','C','D'),
'B' => array('C','D')
);
$input = array('A', 'B', 'C', 'D');
foreach($input as $key => $value){
$tempKey = $key;
for($key +1 ; $key < count($input) ; $key++){
$result[$tempKey][] = $input[$key];
}
}
You can use this generic method:
function combine($inputArray, &$outputArray, $index, $combLen) {
global $outstr;
for ($i = $index; $i < count($inputArray); $i++) {
$outstr.=$inputArray[$i];
if(strlen($outstr) == $combLen) {
$outputArray[]= $outstr;
}
combine($inputArray, $outputArray, $i + 1, $combLen);
$outstr = substr($outstr, 0, strlen($outstr)-1);
}
}
See it on ideone
if you need to work with pairs as arrays
$pairs = [];
foreach($a as $k => $v) {
foreach(array_slice($a, $k + 1) as $k2 => $v2) {
$pairs[] = [$v, $v2];
}
}
Using PHP, I'd like to convert a string containing a Roman number into its integer representation. I need this because I need to make calculations on them.
Wikipedia on Roman numerals
It would suffice to only recognize the basic Roman numeral characters, like:
$roman_values=array(
'I' => 1,
'V' => 5,
'X' => 10,
'L' => 50,
'C' => 100,
'D' => 500,
'M' => 1000,
);
That means the highest possible number is 3999 (MMMCMXCIX). I will use N to represent zero, other than that only positive integers are supported.
I cannot use the PEAR library for Roman numbers.
I found this great question on SO on how to test whether the string contains a valid Roman numeral:
How do you match only valid roman numerals with a regular expression?
What would be the best way of coding this?
How about this:
$romans = array(
'M' => 1000,
'CM' => 900,
'D' => 500,
'CD' => 400,
'C' => 100,
'XC' => 90,
'L' => 50,
'XL' => 40,
'X' => 10,
'IX' => 9,
'V' => 5,
'IV' => 4,
'I' => 1,
);
$roman = 'MMMCMXCIX';
$result = 0;
foreach ($romans as $key => $value) {
while (strpos($roman, $key) === 0) {
$result += $value;
$roman = substr($roman, strlen($key));
}
}
echo $result;
which should output 3999 for the supplied $roman. It seems to work for my limited testing:
MCMXC = 1990
MM = 2000
MMXI = 2011
MCMLXXV = 1975
You might want to do some validation first as well :-)
I am not sure whether you've got ZF or not, but in case you (or any of you who's reading this) do here is my snippet:
$number = new Zend_Measure_Number('MCMLXXV', Zend_Measure_Number::ROMAN);
$number->convertTo (Zend_Measure_Number::DECIMAL);
echo $number->getValue();
Zend_Measure_Number on framework.zend.com
This is the one I came up with, I added the validity check as well.
class RomanNumber {
//array of roman values
public static $roman_values=array(
'I' => 1, 'V' => 5,
'X' => 10, 'L' => 50,
'C' => 100, 'D' => 500,
'M' => 1000,
);
//values that should evaluate as 0
public static $roman_zero=array('N', 'nulla');
//Regex - checking for valid Roman numerals
public static $roman_regex='/^M{0,3}(CM|CD|D?C{0,3})(XC|XL|L?X{0,3})(IX|IV|V?I{0,3})$/';
//Roman numeral validation function - is the string a valid Roman Number?
static function IsRomanNumber($roman) {
return preg_match(self::$roman_regex, $roman) > 0;
}
//Conversion: Roman Numeral to Integer
static function Roman2Int ($roman) {
//checking for zero values
if (in_array($roman, self::$roman_zero)) {
return 0;
}
//validating string
if (!self::IsRomanNumber($roman)) {
return false;
}
$values=self::$roman_values;
$result = 0;
//iterating through characters LTR
for ($i = 0, $length = strlen($roman); $i < $length; $i++) {
//getting value of current char
$value = $values[$roman[$i]];
//getting value of next char - null if there is no next char
$nextvalue = !isset($roman[$i + 1]) ? null : $values[$roman[$i + 1]];
//adding/subtracting value from result based on $nextvalue
$result += (!is_null($nextvalue) && $nextvalue > $value) ? -$value : $value;
}
return $result;
}
}
Quick idea - go through the Roman number from right to left, if value of $current (more to the left) is smaller than $previous, then subtract it from the result, if larger, then add it.
$romanValues=array(
'I' => 1,
'V' => 5,
'X' => 10,
'L' => 50,
'C' => 100,
'D' => 500,
'M' => 1000,
);
$roman = 'MMMCMXCIX';
// RTL
$arabic = 0;
$prev = null;
for ( $n = strlen($roman) - 1; $n >= 0; --$n ) {
$curr = $roman[$n];
if ( is_null($prev) ) {
$arabic += $romanValues[$roman[$n]];
} else {
$arabic += $romanValues[$prev] > $romanValues[$curr] ? -$romanValues[$curr] : +$romanValues[$curr];
}
$prev = $curr;
}
echo $arabic, "\n";
// LTR
$arabic = 0;
$romanLength = strlen($roman);
for ( $n = 0; $n < $romanLength; ++$n ) {
if ( $n === $romanLength - 1 ) {
$arabic += $romanValues[$roman[$n]];
} else {
$arabic += $romanValues[$roman[$n]] < $romanValues[$roman[$n+1]] ? -$romanValues[$roman[$n]] : +$romanValues[$roman[$n]];
}
}
echo $arabic, "\n";
Some validation of roman number should also be added, though you said that you already have found how to do it.
Copyrights is for this blog (btw!)
http://scriptsense.blogspot.com/2010/03/php-function-number-to-roman-and-roman.html
<?php
function roman2number($roman){
$conv = array(
array("letter" => 'I', "number" => 1),
array("letter" => 'V', "number" => 5),
array("letter" => 'X', "number" => 10),
array("letter" => 'L', "number" => 50),
array("letter" => 'C', "number" => 100),
array("letter" => 'D', "number" => 500),
array("letter" => 'M', "number" => 1000),
array("letter" => 0, "number" => 0)
);
$arabic = 0;
$state = 0;
$sidx = 0;
$len = strlen($roman);
while ($len >= 0) {
$i = 0;
$sidx = $len;
while ($conv[$i]['number'] > 0) {
if (strtoupper(#$roman[$sidx]) == $conv[$i]['letter']) {
if ($state > $conv[$i]['number']) {
$arabic -= $conv[$i]['number'];
} else {
$arabic += $conv[$i]['number'];
$state = $conv[$i]['number'];
}
}
$i++;
}
$len--;
}
return($arabic);
}
function number2roman($num,$isUpper=true) {
$n = intval($num);
$res = '';
/*** roman_numerals array ***/
$roman_numerals = array(
'M' => 1000,
'CM' => 900,
'D' => 500,
'CD' => 400,
'C' => 100,
'XC' => 90,
'L' => 50,
'XL' => 40,
'X' => 10,
'IX' => 9,
'V' => 5,
'IV' => 4,
'I' => 1
);
foreach ($roman_numerals as $roman => $number)
{
/*** divide to get matches ***/
$matches = intval($n / $number);
/*** assign the roman char * $matches ***/
$res .= str_repeat($roman, $matches);
/*** substract from the number ***/
$n = $n % $number;
}
/*** return the res ***/
if($isUpper) return $res;
else return strtolower($res);
}
/* TEST */
echo $s=number2roman(1965,true);
echo "\n and bacK:\n";
echo roman2number($s);
?>
I'm late to the party, but here's mine. Assumes valid Numerals in the string, but doesn't test for a valid Roman number, whatever that is...there doesn't seem to be a consensus. This function will work for Roman numbers like VC (95), or MIM (1999), or MMMMMM (6000).
function roman2dec( $roman ) {
$numbers = array(
'I' => 1,
'V' => 5,
'X' => 10,
'L' => 50,
'C' => 100,
'D' => 500,
'M' => 1000,
);
$roman = strtoupper( $roman );
$length = strlen( $roman );
$counter = 0;
$dec = 0;
while ( $counter < $length ) {
if ( ( $counter + 1 < $length ) && ( $numbers[$roman[$counter]] < $numbers[$roman[$counter + 1]] ) ) {
$dec += $numbers[$roman[$counter + 1]] - $numbers[$roman[$counter]];
$counter += 2;
} else {
$dec += $numbers[$roman[$counter]];
$counter++;
}
}
return $dec;
}
Whew! Those are quite a few answers, and made of them are code-heavy! How about we define an algorithm for this first, before I give an answer?
The Basics
Don't store multi-digit Roman numerals, like 'CM' => 900, or anything like that in an array. If you know that M - C (1000 - 100) equals 900, then ultimately, you should only be storing the values of 1000 and 100. You wouldn't have multi-digit Roman numerals like CMI for 901, would you? Any answer that does this will be inefficient from one that understands the Roman syntax.
The Algorithm
Example: LIX (59)
Do a for loop on the numbers, starting at the end of the string of Roman numerals. In our example: We start on "X".
Greater-Than-Equal-To Case — If the value we are looking at is the same or greater than the last value, simply add it to a cumulative result. In our example: $result += $numeral_values["X"].
Less-Than Case — If the value we are subtracting is less than the previous number, we subtract it from our cumulative result. In our example IX, I is 1 and X is 10, so, since 1 is less than 10, we subtract it: giving us 9.
The Demo
Full Working Demo Online
The Code
function RomanNumeralValues() {
return [
'I'=>1,
'V'=>5,
'X'=>10,
'L'=>50,
'C'=>100,
'D'=>500,
'M'=>1000,
];
}
function ConvertRomanNumeralToArabic($input_roman){
$input_length = strlen($input_roman);
if($input_length === 0) {
return $result;
}
$roman_numerals = RomanNumeralValues();
$current_pointer = 1;
$result = 0;
for($i = $input_length - 1; $i > -1; $i--){
$letter = $input_roman[$i];
$letter_value = $roman_numerals[$letter];
if($letter_value === $current_pointer) {
$result += $letter_value;
} elseif ($letter_value < $current_pointer) {
$result -= $letter_value;
} else {
$result += $letter_value;
$current_pointer = $letter_value;
}
}
return $result;
}
print ConvertRomanNumeralToArabic("LIX");
function romanToInt($s) {
$array = ["I"=>1,"V"=>5,"X"=>10,"L"=>50,"C"=>100,"D"=>500,"M"=>1000];
$sum = 0;
for ($i = 0; $i < strlen($s); $i++){
$curr = $s[$i];
$next = $s[$i+1];
if ($array[$curr] < $array[$next]) {
$sum += $array[$next] - $array[$curr];
$i++;
} else {
$sum += $array[$curr];
}
}
return $sum;
}
Define your own schema! (optional)
function rom2arab($rom,$letters=array()){
if(empty($letters)){
$letters=array('M'=>1000,
'D'=>500,
'C'=>100,
'L'=>50,
'X'=>10,
'V'=>5,
'I'=>1);
}else{
arsort($letters);
}
$arab=0;
foreach($letters as $L=>$V){
while(strpos($rom,$L)!==false){
$l=$rom[0];
$rom=substr($rom,1);
$m=$l==$L?1:-1;
$arab += $letters[$l]*$m;
}
}
return $arab;
}
Inspired by andyb's answer
I just wrote this in about 10 mins, it's not perfect, but seems to work for the few test cases I've given it. I'm not enforcing what values are allowed to be subtracted from what, this is just a basic loop that compares the current letter value with the next one in the sequence (if it exists) and then either adds the value or adds the subtracted amount to the total:
$roman = strtolower($_GET['roman']);
$values = array(
'i' => 1,
'v' => 5,
'x' => 10,
'l' => 50,
'c' => 100,
'd' => 500,
'm' => 1000,
);
$total = 0;
for($i=0; $i<strlen($roman); $i++)
{
$v = $values[substr($roman, $i, 1)];
$v2 = ($i < strlen($roman))?$values[substr($roman, $i+1, 1)]:0;
if($v2 && $v < $v2)
{
$total += ($v2 - $v);
$i++;
}
else
$total += $v;
}
echo $total;
Just stumbled across this beauty and have to post it all over:
function roman($N)
{
$c = 'IVXLCDM';
for ($a = 5, $b = $s = ''; $N; $b++, $a ^= 7)
{
for (
$o = $N % $a, $N = $N / $a ^ 0;
$o--;
$s = $c[$o > 2 ? $b + $N - ($N &= -2) + $o = 1 : $b] . $s
);
}
return $s;
}
function Romannumeraltonumber($input_roman){
$di=array('I'=>1,
'V'=>5,
'X'=>10,
'L'=>50,
'C'=>100,
'D'=>500,
'M'=>1000);
$result=0;
if($input_roman=='') return $result;
//LTR
for($i=0;$i<strlen($input_roman);$i++){
$result=(($i+1)<strlen($input_roman) and
$di[$input_roman[$i]]<$di[$input_roman[$i+1]])?($result-$di[$input_roman[$i]])
:($result+$di[$input_roman[$i]]);
}
return $result;
}
function rom_to_arabic($number) {
$symbols = array(
'M' => 1000,
'D' => 500,
'C' => 100,
'L' => 50,
'X' => 10,
'V' => 5,
'I' => 1);
$a = str_split($number);
$i = 0;
$temp = 0;
$value = 0;
$q = count($a);
while($i < $q) {
$thys = $symbols[$a[$i]];
if(isset($a[$i +1])) {
$next = $symbols[$a[$i +1]];
} else {
$next = 0;
}
if($thys < $next) {
$value -= $thys;
} else {
$value += $thys;
}
$temp = $thys;
$i++;
}
return $value;
}
function parseRomanNumerals($input)
{
$roman_val = '';
$roman_length = strlen($input);
$result_roman = 0;
for ($x = 0; $x <= $roman_length; $x++) {
$roman_val_prev = $roman_val;
$roman_numeral = substr($input, $roman_length-$x,1);
switch ($roman_numeral) {
case "M":
$roman_val = 1000;
break;
case "D":
$roman_val = 500;
break;
case "C":
$roman_val = 100;
break;
case "L":
$roman_val = 50;
break;
case "X":
$roman_val = 10;
break;
case "V":
$roman_val = 5;
break;
case "I":
$roman_val = 1;
break;
default:
$roman_val = 0;
}
if ($roman_val_prev<$roman_val) {
$result_roman = $result_roman - $roman_val;
}
else {
$result_roman = $result_roman + $roman_val;
}
}
return abs($result_roman);
}
I would like to check if my array has any duplicates and return the duplicated values in an array.
I want this to be as efficient as possible.
Example:
$array = array( 1, 2, 2, 4, 5 );
function return_dup($array); // should return 2
$array2 = array( 1, 2, 1, 2, 5 );
function return_dup($array2); // should return an array with 1,2
Also the initial array is always 5 positions long
this will be ~100 times faster than array_diff
$dups = array();
foreach(array_count_values($arr) as $val => $c)
if($c > 1) $dups[] = $val;
You can get the difference of the original array and a copy without duplicates using array_unique and array_diff_assoc:
array_diff_assoc($arr, array_unique($arr))
function array_dup($ar){
return array_unique(array_diff_assoc($ar,array_unique($ar)));
}
Should do the trick.
You can do like this:
function showDups($array)
{
$array_temp = array();
foreach($array as $val)
{
if (!in_array($val, $array_temp))
{
$array_temp[] = $val;
}
else
{
echo 'duplicate = ' . $val . '<br />';
}
}
}
$array = array(1,2,2,4,5);
showDups($array);
Output:
duplicate = 2
function returndup($array)
{
$results = array();
$duplicates = array();
foreach ($array as $item) {
if (in_array($item, $results)) {
$duplicates[] = $item;
}
$results[] = $item;
}
return $duplicates;
}
in addition to gumbo's answer:
function returndup($arr)
{
return array_diff_key($arr, array_unique($arr));
}
I did some tests and indeed #user187291's variant is the fastest. But, it turns out that #Gumbo's and #faebser's alternative are almost as fast, #faebser's being just slightly faster than #Gumbo's and sometimes even fastest of all.
Here's the code I used
$array = array(1, "hello", 1, "world", "hello");
$times = 1000000;
$start = microtime(true);
for ($i = 0; $i < $times; $i++) {
$dups = array();
foreach(array_count_values($array) as $val => $c)
if( $c > 1) $dups[] = $val;
}
$end = microtime(true);
echo 'variant 1 (user187291): ' . ($end - $start);
echo '<br><br><br>';
$start = microtime(true);
for ($i = 0; $i < $times; $i++)
$dups = array_unique(array_diff_assoc($array, array_unique($array)));
$end = microtime(true);
echo 'variant 2 (JAL): ' . ($end - $start);
echo '<br><br><br>';
$start = microtime(true);
for ($i = 0; $i < $times; $i++)
$dups = array_diff_assoc($array, array_unique($array));
$end = microtime(true);
echo 'variant 3 (Gumbo): ' . ($end - $start);
echo '<br><br><br>';
$start = microtime(true);
for ($i = 0; $i < $times; $i++)
$dups = array_diff_key($array, array_unique($array));
$end = microtime(true);
echo 'variant 4 (faebser): ' . ($end - $start);
echo '<br><br><br>';
I have found another way to return duplicates in an array
function printRepeating($arr, $size)
{
$i;
$j;
for($i = 0; $i < $size; $i++)
for($j = $i + 1; $j < $size; $j++)
if($arr[$i] == $arr[$j])
echo $arr[$i], " ";
}
printRepeating($array, sizeof($array,0);
If you need a solution that will work with an array of arrays (or any array values other than integers or strings) try this:
function return_dup( $arr ) {
$dups = array();
$temp = $arr;
foreach ( $arr as $key => $item ) {
unset( $temp[$key] );
if ( in_array( $item, $temp ) ) {
$dups[] = $item;
}
}
return $dups;
}
$arr = array(
array(
0 => 'A',
1 => 'B',
),
array(
0 => 'A',
1 => 'B',
),
array(
0 => 'C',
1 => 'D',
),
array(
0 => 'C',
1 => 'D',
),
array(
0 => 'E',
1 => 'F',
),
array(
0 => 'F',
1 => 'E',
),
array(
0 => 'Y',
1 => 'Z',
),
);
var_export( return_dup( $arr ) );
/*
array (
0 => array (
0 => 'A',
1 => 'B',
),
1 => array (
0 => 'C',
1 => 'D',
),
)
*/
As per your problem if you have duplicate values then you have to return those values. I write a function for this problem. If your array has duplicate values this function returns these values within the array otherwise it returns null values. Here is an example:
function containsDuplicate($array_values) {
$duplicates_values = [];
for($i = 0; $i < count($array_values); $i++){
for ($j=$i+1; $j <count($array_values) ; $j++) {
if ($array_values[$i] == $array_values[$j]) {
$duplicates_values[] = $array_values[$i];
}
}
}
if(count($duplicates_values) > 0){
return $duplicates_values;
}
}
$duplicate_array = array();
for($i=0;$i<count($array);$i++){
for($j=0;$j<count($array);$j++){
if($i != $j && $array[$i] == $array[$j]){
if(!in_array($array[$j], $duplicate_array)){
$duplicate_array[] = $array[$j];
}
}
}
}