This question already has answers here:
Closed 10 years ago.
Possible Duplicate:
Checking if an array contains all elements of another array
I have posted something like this to the Stackoverflow before, but the answers do not fully satisfy me. That's why I'm posting the question again, but changing the question all along.
Some people helped me to construct a function that checks if an array($GroupOfEight[$i]) that is an element of a multidimensional array($GroupOfEight) equals another array($stackArray), disregarding the number ordering in the arrays.
However, what I need to check is whether the mentioned array($stackArray) contains any another array($GroupOfEight[$i]) in the multidimensional array($GroupOfEight) or not, that means main array($stackArray) can consist more elements than subarrays($GroupOfEight[$i]).
Here is the one working code that I've gathered so far, but need to be modified to the version I want:
<?php
$GroupOfEight = array (
array(0,1,3,2,4,5,7,6),
array(4,5,6,7,15,12,13,14),
array(12,13,15,14,8,9,11,10),
array(2,6,14,10,3,7,15,11),
array(1,3,5,7,13,15,9,11),
array(0,4,12,8,1,5,13,9),
array(0,1,3,2,8,9,11,10)
);
$stackArray = array(0,4,12,1,9,8,5,13,9,2,5,2,10);
/*$stackArray gets value with POST Method by URL parameter.
This is just the example. As you see this array contains
$GroupOfEight[4], and also it contains many other numbers.*/
/* The function given below checks if $stackArray equals any
of the subarrays of $GroupOfEight. However, we want to check
if $stackArray caontains any of the subarrays of function.
If it does, function should return the index number, if it
doesnt it should return -1.*/
function searcheight($stackArray,$GroupOfEight){
for($i=0; $i<count($GroupOfEight);$i++){
$containsSearch = (count(array_intersect($stackArray,$GroupOfEight[$i])) == count($stackArray) && count(array_intersect($stackArray,$GroupOfEight[$i])) == count($GroupOfEight[$i]));
if($containsSearch){
return $i; //This specifies which index in GroupOfEight contains a matching array
}
}
return -1;
}
// Calling the function that is given above.
echo searcheight($stackArray,$GroupOfEight);
?>
Any logical ideas or solutions will kindly be much appreciated. Thanks.
This one is fast:
function contains_array($array){
foreach($array as $value){
if(is_array($value)) {
return true;
}
}
return false;
}
You can try
$GroupOfEight = array(
array(0,1,3,2,4,5,7,6),
array(4,5,6,7,15,12,13,14),
array(12,13,15,14,8,9,11,10),
array(2,6,14,10,3,7,15,11),
array(1,3,5,7,13,15,9,11),
array(0,4,12,8,1,5,13,9),
array(0,1,3,2,8,9,11,10));
$stackArray = array(0,4,12,1,9,8,5,13,9,2,5,2,10);
function searcheight($stackArray, $GroupOfEight) {
$list = array();
for($i = 0; $i < count($GroupOfEight); $i ++) {
$intercept = array_intersect($GroupOfEight[$i], $stackArray);
$len = count($intercept);
if ($len % 4 == 0) {
$list[$i] = $len;
}
}
arsort($list);
if (empty($list))
return - 1;
return key($list);
}
echo searcheight($stackArray, $GroupOfEight);
Output
5
Related
This question already has an answer here:
match exact number in string (and no partial match inside bigger numbers)
(1 answer)
Closed 3 months ago.
Been trying for a while on how to check if a value exists in an array and if so, assign it to a variable to be inserted into the database.
I have the searching working although I can't seem to grab the correct value from the array to which I then need to insert.
Here's where I'm searching for the ID to search by:
{
"questionName": "_questionImgPhoto_176471",
"questionID": "471",
}
Here's the array example:
[0]"/insert/ImgID_466.png"
[1]"/insert/ImgID_471.png"
I am checking if questionID 471 exists somewhere in the array string, if so, insert that row. I am struggling on that part.
So for the insert on questionID 466, the img with 466 in the string will attach to it and so forth.
As you can see 471 does exist in the array example so it should grab that row, here's a snippet of my code below:
for ($i=0; $i < count($content->formValuesT); $i++)
{
if(strpos($content->formValuesT[$i]->questionValue, 'blob') !== false )
{
foreach($content->images_to_upload[$i] as $index => $string) {
if (strpos($string, $content->formValuesT[$i]->questionID) !== FALSE)
{
$file_to_upload = $content->images_to_upload[$i];
}
else
{
echo "wont insert";
}
}
}
}
Has anyone got some pointers or ideas on how to achieve the above? I just can't wrap my head around the practical side of it! in theory I think this is the correct route.
The $file_to_upload is what will be uploaded per row.
Thanks
You can search an array for a specific pattern. Here I made a simple helper function to return the first match or NULL.
$imagesToInsert = ["/insert/ImgID_466.png", "/insert/ImgID_471.png"];
$getImageForId = function(int $id, array $images): ?string {
$matches = preg_grep("/ImgID_{$id}\.png/", $images);
return $matches ? reset($matches) : null;
};
var_dump($getImageForId(471, $imagesToInsert));
var_dump($getImageForId(466, $imagesToInsert));
var_dump($getImageForId(777, $imagesToInsert));
Output
string(21) "/insert/ImgID_471.png"
string(21) "/insert/ImgID_466.png"
NULL
I have the following code, which checks is an element exists, and if it exists, it checks for the same name, with an incremented number at the end.
For example, it checks is the key "test" exists in the array $this->elements, and if it exists, it checks for "test2", and so on, until the key doesn't exist.
My original code is:
if (isset($this->elements[$desired])) {
$inc = 0;
do {
$inc++;
$new_desired = $desired . $inc;
} while (isset($this->elements[$new_desired]));
$desired = $new_desired;
}
I tried with:
if (isset($this->elements[$desired])) {
return $this->generateUniqueElement($desired, $postfix);
}
private function generateUniqueElement($desired, $postfix) {
$new_desired = $desired . $postfix;
return isset($this->elements[$new_desired]) ? $this->generateUniqueElement($desired, ++$postfix) : $new_desired;
}
But in my tests there's no speed improvement.
Any idea how can I improve the code? On all the pages, this code is called over 10 000 times. And sometimes even over 100k times.
Anticipated thanks!
Without further knowledge on how you generate this list, here's an idea:
$highestElementIds = [];
foreach($this->elements as $element) {
preg_match('/(.*?)(\d+)/', $element, $matches);
$text = $matches[1];
$id = (int)$matches[2];
if(!isset($highestElementIds[$text])) {
$highestElementIds[$text] = $id;
} else {
if($id > $highestElementIds[$text]) {
$highestElementIds[$text] = $id;
}
}
}
// find some element by a simple array access
$highestElementIds['test']; // will return 2 in your example
If your code is really being called 100k times, it should be a lot faster to iterate your list only once and then get the highest id directly from an array which contains the highest number (since you don't need to iterate through it again).
That being said, I still wonder what's the actual reason for having such a huge array in the first place...
Typical unique IDs are either random (UUID or random chars) or sequential numbers. The latter is as simple as it gets and it can be generated with a simple counter:
function generateNewElement($postfix) {
static $i = 0;
return sprintf('%d%s', $i++, $postfix);
}
echo generateNewElement('foo'), PHP_EOL;
echo generateNewElement('foo'), PHP_EOL;
echo generateNewElement('foo'), PHP_EOL;
echo generateNewElement('foo'), PHP_EOL;
0foo
1foo
2foo
3foo
Of course this is just a generic solution so it may not fit your specific use case.
I have an array of objects containing a number of values. The values are set correctly and the data inside this array is also shown in correct way accoring to the order of objects.
What i would want now ii that the order is changed. In this particular example according to the objects 'Point' value, so the objects with the highest Pointvalue is first and so on...
What I tried to do was finding the object with the highest value, push it in the array and unsetting the original value. And with array_slice getting the relevant array elements in the end.
I also succeeded in the first part, but the problem is I keep finding the same object, so i somehow doesn't remove it from the array.
$max = $obj[0];
for ($j =0; $j<count($obj)-$j; $j++) {
for ($i=0; $i<count($names); $i++) {
if ($max->Point < $obj[$i+1]->Point) {
$max = $obj[$i+1];
}
}
if ($max->id == $obj[$j]->id) {
unset($obj[$j]);
}
array_push($obj, $max);
}
I'm not sure you can see through the code and what I'm trying to do, but hopefully someone can and either show my mistake(s), or show others way to accomplish the same?
Try using the usort() function. It allows you to sort the array according to a comparison function that you define.
function lower_points($a, $b) {
if ($a->Point == $b->Point) return 0;
else if ($a->Point > $b->Point) return -1;
else return 1;
}
usort($array_of_objects, lower_points);
Closed. This question does not meet Stack Overflow guidelines. It is not currently accepting answers.
Questions concerning problems with code you've written must describe the specific problem — and include valid code to reproduce it — in the question itself. See SSCCE.org for guidance.
Closed 8 years ago.
Improve this question
Is possible to add new values to the array that the foreach is working with? So it will run (n+x) where n is the number of elements of the array before the foreach starts and x is the number of elements that were added to the array.
Yes, I tested.. and looks like NO.. so I'd like to know if I can do something to this work.
foreach($pages_to_visit as $key => $source){
global $products;
$links = baixarSource($source);
foreach($links as $link){
global $products;
global $pages_to_visit;
if(preg_match("/somestore\.com/i", $link)){
if(!in_array($link, $pages_to_visit)){
$pages_to_visit[] = $link;
}else if(preg_match("/\/produto\//i", $link) && !in_array($link, $products)){
$products[] = $link;
echo $link."\n";
}
}
}
unset($pages_to_visit[$key]);
sleep(0.2);
}
As you already figured out, using foreach() it is not possible, however when you use for() the task becomes quite easy:
for ($i=0; $i<count($array); $i++) {
//code
}
This is due to count($array) being (re)calculated before every iteration. You can also use a variable that you increment yourself (incrementing is a way easier task than counting an array)
$max = count($array);
for ($i=0; $i<$max; $i++) {
//code
//when push an element just do $max++;
}
Of course this will only work with numerical indices but that seems to be the case here.
You need to specify the "runner" variable as a reference in the foreach code if you want to modify the array itself from within the foreach.
http://us2.php.net/manual/en/control-structures.foreach.php
In order to be able to directly modify array elements within the loop precede $value with &. In that case the value will be assigned by reference.
Example (will only count to 9):
$arr = array(1,2,3,4,5,6,7,8,9);
$makeArrayLonger = true;
foreach ($arr as $blubb)
{
if ($makeArrayLonger)
{
$arr[] = 10;
$makeArrayLonger = false;
}
echo $blubb;
}
Example2 (this time it will count to 10 using the additional element added from inside the foreach):
$arr = array(1,2,3,4,5,6,7,8,9);
$makeArrayLonger = true;
foreach ($arr as &$blubb)
{
if ($makeArrayLonger)
{
$arr[] = 10;
$makeArrayLonger = false;
}
echo $blubb;
}
Not sure if I get your question right... I think what you try to do doesn't make much sense at all any way.
echo $countBefore = count($data);
foreach ($data $as $value) {
$data[] = 'Some new value';
}
echo $countAfter = count($data);
I have a PHP script which reads a large CSV and performs certain actions, but only if the "username" field is unique. The CSV is used in more than one script, so changing the input from the CSV to only contain unique usernames is not an option.
The very basic program flow (which I'm wondering about) goes like this:
$allUsernames = array();
while($row = fgetcsv($fp)) {
$username = $row[0];
if (in_array($username, $allUsernames)) continue;
$allUsernames[] = $username;
// process this row
}
Since this CSV could actually be quite large, it's that in_array bit which has got me thinking. The most ideal situation when searching through an array for a member is if it is already sorted, so how would you build up an array from scratch, keeping it in order? Once it is in order, would there be a more efficient way to search it than using in_array(), considering that it probably doesn't know the array is sorted?
Not keeping the array in order, but how about this kind of optimization? I'm guessing isset() for an array key should be faster than in_array() search.
$allUsernames = array();
while($row = fgetcsv($fp)) {
$username = $row[0];
if (isset($allUsernames[$username])) {
continue;
} else {
$allUsernames[$username] = true;
// do stuff
}
}
The way to build up an array from scratch in sorted order is an insertion sort. In PHP-ish pseudocode:
$list = []
for ($element in $elems_to_insert) {
$index = binary_search($element, $list);
insert_into_list($element, $list, $index);
}
Although, it might actually turn out to be faster to just create the array in unsorted order and then use quicksort (PHP's builtin sort functions use quicksort)
And to find an element in a sorted list:
function binary_search($list, $element) {
$start = 0;
$end = count($list);
while ($end - $start > 1) {
$mid = ($start + $end) / 2;
if ($list[$mid] < $element){
$start = $mid;
}
else{
$end = $mid;
}
}
return $end;
}
With this implementation you'd have to test $list[$end] to see if it is the element you want, since if the element isn't in the array, this will find the point where it should be inserted. I did it that way so it'd be consistent with the previous code sample. If you want, you could check $list[$end] === $element in the function itself.
The array type in php is an ordered map (php array type). If you pass in either ints or strings as keys, you will have an ordered map...
Please review item #6 in the above link.
in_array() does not benefit from having a sorted array. PHP just walks along the whole array as if it were a linked list.