Jump to content

[SOLVED] Is there a more efficient way to code this than what I have?


Recommended Posts

I have three associative arrays. 

 

$combinedSettings

$userSettings

$defaultSettings

 

My function must combine the key and value from $userSettings and $defaultSettings into the $combinedSettings array. 

 

$userSettings will always contain more keys than $defaultSettings will ever have. 

 

So every once in a while there is an extra key and of course it's value in the $userSettings array than in the $defaultSettings array. 

 

If the value of a key in $userSettings is empty we then use the value for the same key in the $defaultSettings.  Every key in $defaultSettings will always be present in $userSettings.  $userSettings just adds a few extra keys and their values.

 

Below is my working code but I am wondering if there is some way to make it more efficient, faster, perhaps with less code.  It looks rather clutzy to me.  Rather bloated. 

 

      while (list($userKey, $userValue) = each($userSettings)) {
         while ($defaultKey = key($defaultSettings)) {
            $defaultValue = current($defaultSettings);
            if ($userKey === $defaultKey) {
               if ($userValue === "") {
                  $combinedSettings[$defaultKey] = $defaultValue;
               } else {
                  $combinedSettings[$userKey] = $userKey;
               }
               next($defaultSettings); // to allow key() to work properly above.
            } else { // add userSettings setting and value to combinedSettings and leave
                     // defaultSettings where it is.
               $combinedSettings[$userKey] = $userValue;
            }
            break;
         }
      }

 

Thanks.

 

Carlos

array_merge() definitely does not do what I need Mark.  It always takes the value of the second array when merging if the two keys are the same. 

 

For my needs $userSettings (the first array) always has precedence in the merge unless it is blank in which case I take the value in the same key in the $defaultSettings array. 

 

array_match() also appends new keys and their values to the end of the combined array which I do not want.  I want keys to be inserted in their proper place in the order of keys. 

 

Thanks for the suggestion though. 

 

Carlos

Yes...using a database is out of the question. I am developing a simplified web site creation system that involves reading a userSetting and defaultSetting ini files for it's settings. 

 

The system does not use the overhead of a database on purpose since it is meant to be lean and mean for the purpose of creating simple web sites like the kind that one needs to create for Adsense.

 

Even if I stored the values of userSettings and defaultSettings in a database it would not alleviate me of having to figure out how to combine their values on the fly. Since my system accepts as input only one set of settings that are then used as the active settings to use.

 

The code I posted works but I am just wondering if there is a more efficient way to do it. 

 

Actually I had to fix something in the code...the code below is what actually works as intended.

 

      while (list($userKey, $userValue) = each($userSettings)) {
         while ($defaultKey = key($defaultSettings)) {
            $defaultValue = current($defaultSettings);
            if ($userKey === $defaultKey) {
               if ($userValue === "") {
                  $combinedSettings[$defaultKey] = $defaultValue;
               } else {
                  $combinedSettings[$userKey] = $userValue;
               }
               next($defaultSettings); // to allow key() to work properly above.
            } else { // leave defaultSettings where it is but collect the right key/value into
                       // combinedSettings array.
               if ($userValue === "") {
                  $combinedSettings[$defaultKey] = $defaultValue;
               } else {
                  $combinedSettings[$userKey] = $userValue;
               }
            }
            break;
         }
      }

 

Carlos

I would do it like so

function combine($array1, $array2){//array1 has precedence
$combined=array_merge($array2, $array1);
//merge them all with array1 having precedence.
//array merge will overwrite any default values, even if 
//the value is empty (ie "")


//now go through, and replace any empty values with
//their default values
$keys = array_keys($array2);
foreach($keys as $key){
if ($combined[$key] == "" || empty($combined[$key])){
//if we find a key in combined thats empty
//replace it with default value
$combined[$key] = $array2[$key];
}//end if
}//end foreach
}//end func

Hmm...interesting solution you have there Mike.  Very good!  I will have to toy around with that some.  Don't know if it's faster but then again my code operates fast enough so I am sure your solution will be more than adequate. It's certainly cleaner looking.

 

The only "problem" which is really not a problem is that the keys will not be in the same order more or less as the order that they are found in inside the respective user and default setting files.  But really the order of the keys in the arrays is only good for debugging.  Once the code works flawlessly it won't matter what order the keys are in. 

 

Thanks for the tip! 

 

Carlos

You could use array sort to put them in alphabetical order.

 

As for faster or not, either one would only be slightly faster than the other. Unless you are processing GIGANTIC arrays, then you won't really see a difference. You could time it though, if you are curious. just do both 100 times, like

 

$time = time();
for($i = 0; $i < 100; $i++){ 
yourMethod();
}
echo "Us: ". (time() - $time) ."<br />";
$time = time();
for($i = 0; $i < 100; $i++){ 
myMethod();
}
echo "and Them: ". (time() - $time) ."<br />";

 

edit: if you are processing huge arrays, I would just use databases. it would definitely be faster

Thanks again Mike but my arrays won't ever be bigger than about 50 settings if that.  So speed wise like you said...it won't make any bit of difference at least respecting anything that would be visible by the naked eye. 

 

I like your sorting idea except that my settings are grouped together and are not in alphabetical order in the ini files.  But the internal ordering of the elements in the arrays that these settings are read into is only useful for me in debugging things.  Once things are fully debugged the internal order of what is read into the arrays won't make any difference at all.

 

Thanks again Mike. 

 

Carlos

 

I am wondering if there is some way to make it more efficient, faster, perhaps with less code.

yes.. see below code.

$userArray = array();
$defaultArray = array();
$combinedArray = array();

foreach($userArray as $k=>$v)
    if(empty($userArray[$k]) || is_null($userArray[$k])) $userArray[$k] = $defaultArray[$k];

 

nevermind above.. misunderstood.

 

$userArray = array();
$defaultArray = array();
$combinedArray = array();

foreach($userArray as $k=>$v) {
    if(empty($userArray[$k]) || is_null($userArray[$k])) $combinedArray[$k] = $defaultArray[$k];
    else $combinedArray[$k] = $userArray[$k];
}

Thanks Zanus but it does not seem that your solution will do what I need.  You see $k is not consistent as the right key between $userArray and $defaultArray as your solution supposes it is. 

 

$userArray has additional keys (with their corresponding values) more than $defaultArray. 

 

In other words every key in $defaultArray is also found in $userArray but $userArray has addtional keys not found in $defaultArray. 

 

What I originally had been trying to do was insert the extra keys from $userArray into $combinedArray just below the key in $defaultArray that it was related to. 

 

Let me give an example...

 

$userArray keys and values:

 

PageBackgroundImage=

PageBackgroundImageUsed=yes

ContentBackgroundImage=images/new-background.png

ContentBackgroundImageUsed=no

 

$defaultArray key and values:

 

PageBackgroundImage=images/page-background.png

ContentBackgroundImage=images/content-background.png

 

What I would want to end up in $combinedArray would be: 

 

PageBackgroundImage=images/page-background.png

PageBackgroundImageUsed=yes

ContentBackgroundImage=images/new-background.png

ContentBackgroundImageUsed=no

 

Settings in $userArray take precedence over any settings in $defaultArray. 

 

Notice how the appropriate ....Used setting is inserted below the one that it applies to? 

 

That is what I originally had in mind and did with my code. 

 

I am going to flag this as solved for my purposes at this point since it does not seem that there is any really more efficient way to do this other than what has been proposed in the thread so far. 

 

Thanks again for the input you all.  Much appreciated! 

 

Carlos

 

 

Thanks Zanus but it does not seem that your solution will do what I need.  You see $k is not consistent as the right key between $userArray and $defaultArray as your solution supposes it is.

How does this not do exactly that?

$userArray = array();
$defaultArray = array();
$combinedArray = array();

$defaultArray['PageBackgroundImage'] = '';
$defaultArray['ContentBackgroundImage'] = 'default-content-image.jpg';

$userArray['PageBackgroundImage'] = '';
$userArray['ContentBackgroundImage'] = 'users-content-image.jpg';
$userArray['PageBackgroundImageUsed'] = 'yes';
$userArray['ContentBackgroundImageUsed'] = 'no';

echo "Defaults";
echo "", print_r($defaultArray), "";
echo "User-Defined";
echo "", print_r($userArray), "";

foreach($userArray as $k=>$v) {
    if(empty($userArray[$k]) || is_null($userArray[$k])) $combinedArray[$k] = $defaultArray[$k];
    else $combinedArray[$k] = $userArray[$k];
}

echo "Combined";
echo "", print_r($combinedArray), "";
?>

 

The Output:

Defaults

 

Array

(

    [PageBackgroundImage] =>

    [ContentBackgroundImage] => default-content-image.jpg

)

1

 

User-Defined

 

Array

(

    [PageBackgroundImage] =>

    [ContentBackgroundImage] => users-content-image.jpg

    [PageBackgroundImageUsed] => yes

    [ContentBackgroundImageUsed] => no

)

1

 

Combined

 

Array

(

    [PageBackgroundImage] =>

    [ContentBackgroundImage] => users-content-image.jpg

    [PageBackgroundImageUsed] => yes

    [ContentBackgroundImageUsed] => no

)

1

 

EDIT:

whooa... I hardly looked at that

Ah, I forgot to set the default PageBackground

$userArray = array();
$defaultArray = array();
$combinedArray = array();

$defaultArray['PageBackgroundImage'] = 'default-image.jpg';

echo "Defaults";
[...]

 

The Output:

Defaults

 

Array

(

    [PageBackgroundImage] => default-image.jpg

    [ContentBackgroundImage] => default-content-image.jpg

)

1

 

User-Defined

 

Array

(

    [PageBackgroundImage] =>

    [ContentBackgroundImage] => users-content-image.jpg

    [PageBackgroundImageUsed] => yes

    [ContentBackgroundImageUsed] => no

)

1

 

Combined

 

Array

(

    [PageBackgroundImage] => default-image.jpg

    [ContentBackgroundImage] => users-content-image.jpg

    [PageBackgroundImageUsed] => yes

    [ContentBackgroundImageUsed] => no

)

1

 

Works like a charm for me

Hmm....I'll have to take a second and closer look at your code Zanus.  Maybe you came up with a solution that was so...well...elegant that it flew over my head :)

 

Thanks for going through the trouble of explaining your solution more.  I will see about getting back to this later today.  I have so much on my plate this morning that I just can't get to it right away. 

 

Carlos

This thread is more than a year old. Please don't revive it unless you have something important to add.

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.

Guest
Reply to this topic...

×   Pasted as rich text.   Restore formatting

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

×
×
  • Create New...

Important Information

We have placed cookies on your device to help make this website better. You can adjust your cookie settings, otherwise we'll assume you're okay to continue.