দুটি পিএইচপি অবজেক্টগুলিকে মার্জ করার জন্য সেরা পদ্ধতি কী?


222

আমাদের দুটি পিএইচপি 5 অবজেক্ট রয়েছে এবং আমরা একটির সামগ্রীতে দ্বিতীয়টিতে মার্জ করতে চাই। তাদের মধ্যে সাবক্লাসের কোনও ধারণা নেই তাই নীচের বিষয়ে বর্ণিত সমাধানগুলি প্রয়োগ করতে পারে না।

আপনি কীভাবে কোনও পৃথক অবজেক্টের মধ্যে পিএইচপি অবজেক্টটি অনুলিপি করেন

//We have this:
$objectA->a;
$objectA->b;
$objectB->c;
$objectB->d;

//We want the easiest way to get:
$objectC->a;
$objectC->b;
$objectC->c;
$objectC->d;

মন্তব্য:

  • এগুলি ক্লাস নয়, বস্তু।
  • অবজেক্টগুলিতে বেশ কয়েকটি ক্ষেত্র রয়েছে যাতে একটি ভবিষ্যদ্বাণী বেশ ধীর হবে।
  • এখনও অবধি আমরা বস্তু A এবং B কে অ্যারেগুলিতে রূপান্তরিত করে তারপরে অ্যারে_ড্যামার () ব্যবহার করে মার্জ করে পুনরায় রূপান্তর করার আগে কোনও বস্তুতে পরিণত করি তবে আমরা বলতে পারি না যে এটি গর্বিত।

30
"অবজেক্টগুলিতে বেশ কয়েকটি ক্ষেত্র রয়েছে তাই একটি ভবিষ্যদ্বাণী যথেষ্ট ধীর হবে" " - কম্পিউটারগুলি বেশ দ্রুত, 'বেশ ধীর' ​​প্রায়শই দ্রুত হয়।
শন ম্যাকসোমিংথিং

উত্তর:


435

যদি আপনার অবজেক্টগুলিতে কেবল ক্ষেত্র থাকে (কোনও পদ্ধতি নেই) তবে এটি কাজ করে:

$obj_merged = (object) array_merge((array) $obj1, (array) $obj2);

যখন বস্তুর পদ্ধতি থাকে তখন এটি বাস্তবেও কাজ করে। (পিএইচপি 5.3 এবং 5.6 দিয়ে পরীক্ষিত)


1
গভীর অনুলিপি ব্যবহারের জন্য আপনি অ্যারে_ড্যামার_ক্র্যাসিভও ব্যবহার করতে পারেন। আপনি অ্যারে_রেপ্লেস_রেকর্ডেও আগ্রহী হতে পারেন। পার্থক্যগুলি এখানে বিশদে
ভিনসেন্ট পাজেলার

12
এর ফলে প্রাপ্ত বস্তুর উদাহরণ হতে পারে stdclass। যদিও এটি পদ্ধতিগুলির সাহায্যে বস্তুগুলিতে এক অর্থে "কাজ" করে, এটি কার্যকরভাবে সেই ক্ষেত্রে (পদ্ধতিগুলি সরিয়ে দিয়ে) বস্তুকে নষ্ট করে দেয়।
ব্রিল্যান্ড

এটি একক ফাংশনে একাধিক ফলাফলের ফলাফলগুলি ফেরত দেওয়ার জন্য দরকারী (এবং কী-মানযুক্ত জোড়া দিয়ে কেবল কোনও বস্তুটি ফিরিয়ে দিন))
লিওনেল এটেনসিও

1
অবজেক্টে একটি পূর্ণসংখ্যা কী থাকলে এটি কাজ করবে না। নিম্নলিখিত উদাহরণটি বিবেচনা করুন: r arr1 = অ্যারে ('a' => 9, 'বি' => 'এস্যাসেড'); r arr2 = অ্যারে ('a' => 10, 'd' => 'কিওয়ার্ট', 0 => 100, 1 => 200, 4 => 400); $ arr3 = অ্যারে_সেমে ($ arr1, $ arr2); প্রতিধ্বনি (মুদ্রণ_আর ($ এআর 3, 1)); আসল আউটপুট: অ্যারে ([a] => 10 [বি] => স্যাসিড [d] => কিয়ার্ট [0] => 100 [1] => 200 [2] => 400) আকাঙ্ক্ষিত আউটপুট: অ্যারে ([এ]] => 10 [খ] => এ্যাসারড [d] => কিওয়ার্ট [0] => 100 [1] => 200 [4] => 400)
সৌভিক

2
এটি কি কেবলমাত্র আমি বা এই উত্তরটি ইতিমধ্যে কয়েক মাস ধরে পোস্ট করা একটি উত্তরটির ভারব্যাটিম অনুলিপি? stackoverflow.com/a/794356/151509
maryisdead

28

আপনি অন্য একটি অবজেক্ট তৈরি করতে পারেন যা অন্তর্নিহিত অবজেক্টগুলিতে যাদু পদ্ধতিতে কল প্রেরণ করে। আপনি কীভাবে পরিচালনা করবেন তা এখানে রয়েছে __getতবে এটি পুরোপুরি কাজ করতে আপনাকে সমস্ত প্রাসঙ্গিক যাদু পদ্ধতি ওভাররাইড করতে হবে। আমি কেবল আমার মাথার উপরের অংশটি প্রবেশ করানোর পরে আপনাকে সম্ভবত বাক্য গঠন ত্রুটিগুলি খুঁজে পাবেন।

class Compositor {
  private $obj_a;
  private $obj_b;

  public function __construct($obj_a, $obj_b) {
    $this->obj_a = $obj_a;
    $this->obj_b = $obj_b;
  }

  public function __get($attrib_name) {
    if ($this->obj_a->$attrib_name) {
       return $this->obj_a->$attrib_name;
    } else {
       return $this->obj_b->$attrib_name;
    }
  }
}

শুভকামনা।


সম্পূর্ণ বাস্তবায়নের জন্য সম্ভবত __isset (), __unset () প্রয়োজন হবে এবং ইন্টারেটার ইন্টারফেস প্রয়োগ করতে হবে।
কর্নেল

@ পার্নেল: ইন্টারেটার ইন্টারফেস কী?
পিম জাগার

2
আমি তার মন্তব্যটি সম্পাদনা করব, তবে আপনি এটি করতে পারবেন না। আমি মনে করি তিনি ইটেটর মানে
আল্লায়েন লালনডে

আমি আপনার সমাধানটি খুব পছন্দ করি, আল্লিন, তবে আমি ভয় পাচ্ছি এর অর্থ এটি ব্যবহারের সিদ্ধান্ত নিলে আমাদের সম্পূর্ণ অ্যাপ্লিকেশনটি নতুন করে লিখতে হবে।
Veynom

3
ঠিক আছে ... তারপরে এমন একটি পথ বেছে নিন যাতে সম্পূর্ণ লেখার প্রয়োজন হয় না।
আল্লায় লালনোদে

25
foreach($objectA as $k => $v) $objectB->$k = $v;

6
এটি পিএইচপি সংস্করণ <7 এর স্বীকৃত উত্তরের চেয়ে দ্রুত (আনুমানিক 50% দ্রুত)। তবে পিএইচপি> = 7-তে গৃহীত উত্তরগুলি 400% দ্রুতগতির মতো। এখানে দেখুন: স্যান্ডবক্স.অনলাইনপ্পফিউশনস
কোড

আমরা কীভাবে এখানে মার্জড ডেটা ব্যবহার করতে বা পেতে পারি?

1
@ ইরামডজু এই উদাহরণে $objectBমার্জড ডেটা ধারণ করে।
কর্নেল

10

আমি বুঝতে পারি যে জেনেরিক বস্তুগুলি [stdClass ()] ব্যবহার করে এবং অ্যারে হিসাবে এগুলি ছড়িয়ে দেওয়া প্রশ্নের উত্তর দেয় তবে আমি মনে করি কমপোসিটারটি একটি দুর্দান্ত উত্তর। তবুও আমি অনুভব করেছি এটি কিছু বৈশিষ্ট্য বর্ধন ব্যবহার করতে পারে এবং অন্য কারও জন্য কার্যকর হতে পারে।

বৈশিষ্ট্য:

  • রেফারেন্স বা ক্লোন নির্দিষ্ট করুন
  • অগ্রাধিকার নিতে প্রথম বা শেষ এন্ট্রি নির্দিষ্ট করুন
  • একাধিক (দু'জনের বেশি) অবজেক্ট অ্যারে_ড্র্যামের সিনট্যাক্সের মিলের সাথে মিশে যাচ্ছে
  • পদ্ধতির লিঙ্কিং: $ আপজি-> এফ 1 () -> এফ 2 () -> এফ 3 () ...
  • ডায়নামিক কম্পোজিট: $ আপজে-> মার্জ (...) / * এখানে কাজ করুন * / $ আপজে-> মার্জ (...)

কোড:

class Compositor {

    protected $composite = array();
    protected $use_reference;
    protected $first_precedence;

    /**
     * __construct, Constructor
     *
     * Used to set options.
     *
     * @param bool $use_reference whether to use a reference (TRUE) or to copy the object (FALSE) [default]
     * @param bool $first_precedence whether the first entry takes precedence (TRUE) or last entry takes precedence (FALSE) [default]
     */
    public function __construct($use_reference = FALSE, $first_precedence = FALSE) {
        // Use a reference
        $this->use_reference = $use_reference === TRUE ? TRUE : FALSE;
        $this->first_precedence = $first_precedence === TRUE ? TRUE : FALSE;

    }

    /**
     * Merge, used to merge multiple objects stored in an array
     *
     * This is used to *start* the merge or to merge an array of objects.
     * It is not needed to start the merge, but visually is nice.
     *
     * @param object[]|object $objects array of objects to merge or a single object
     * @return object the instance to enable linking
     */

    public function & merge() {
        $objects = func_get_args();
        // Each object
        foreach($objects as &$object) $this->with($object);
        // Garbage collection
        unset($object);

        // Return $this instance
        return $this;
    }

    /**
     * With, used to merge a singluar object
     *
     * Used to add an object to the composition
     *
     * @param object $object an object to merge
     * @return object the instance to enable linking
     */
    public function & with(&$object) {
        // An object
        if(is_object($object)) {
            // Reference
            if($this->use_reference) {
                if($this->first_precedence) array_push($this->composite, $object);
                else array_unshift($this->composite, $object);
            }
            // Clone
            else {
                if($this->first_precedence) array_push($this->composite, clone $object);
                else array_unshift($this->composite, clone $object);
            }
        }

        // Return $this instance
        return $this;
    }

    /**
     * __get, retrieves the psudo merged object
     *
     * @param string $name name of the variable in the object
     * @return mixed returns a reference to the requested variable
     *
     */
    public function & __get($name) {
        $return = NULL;
        foreach($this->composite as &$object) {
            if(isset($object->$name)) {
                $return =& $object->$name;
                break;
            }
        }
        // Garbage collection
        unset($object);

        return $return;
    }
}

ব্যবহার:

$obj = new Compositor(use_reference, first_precedence);
$obj->merge([object $object [, object $object [, object $...]]]);
$obj->with([object $object]);

উদাহরণ:

$obj1 = new stdClass();
$obj1->a = 'obj1:a';
$obj1->b = 'obj1:b';
$obj1->c = 'obj1:c';

$obj2 = new stdClass();
$obj2->a = 'obj2:a';
$obj2->b = 'obj2:b';
$obj2->d = 'obj2:d';

$obj3 = new Compositor();
$obj3->merge($obj1, $obj2);
$obj1->c = '#obj1:c';
var_dump($obj3->a, $obj3->b, $obj3->c, $obj3->d);
// obj2:a, obj2:b, obj1:c, obj2:d
$obj1->c;

$obj3 = new Compositor(TRUE);
$obj3->merge($obj1)->with($obj2);
$obj1->c = '#obj1:c';
var_dump($obj3->a, $obj3->b, $obj3->c, $obj3->d);
// obj1:a, obj1:b, obj1:c, obj2:d
$obj1->c = 'obj1:c';

$obj3 = new Compositor(FALSE, TRUE);
$obj3->with($obj1)->with($obj2);
$obj1->c = '#obj1:c';
var_dump($obj3->a, $obj3->b, $obj3->c, $obj3->d);
// obj1:a, obj1:b, #obj1:c, obj2:d
$obj1->c = 'obj1:c';

2
কেবল উল্লেখ করার জন্য: কল-টাইম পাস-বাই-রেফারেন্সটি পিএইচপি 5.3.0 এ অবহিত হিসাবে চিহ্নিত হয়েছে এবং পিএইচপি 5.4.0 এ সরানো হয়েছে (ফলে উত্থাপিত মারাত্মক ত্রুটির ফলস্বরূপ)। ইস্যু ঠিক করার জন্য: প্রতিস্থাপন foreach($objects as &$object) $this->with(&$object);সঙ্গে foreach($objects as &$object) $this->with($object);কারেক্টস সমস্যা। সূত্র: [ php.net/manual/en/language.references.pass.php]
wes.hysell

2
উপরন্তু: if($this->first_precedence) array_push($this->composite, &$object); else array_unshift($this->composite, &$object);উল্লেখ করা আবশ্যকif($this->first_precedence) array_push($this->composite, $object); else array_unshift($this->composite, $object);
wes.hysell

1
সুতরাং আপনার মন্তব্যের সংক্ষিপ্তসার হিসাবে অ্যাম্পারস্যান্ড (এবং) কে $ অবজেক্টের ভিতরে থেকে সরান: ভবিষ্যদ্বাণী (প্রথম মন্তব্য) ... অ্যারে_পুষ্প, অ্যারে_উন্সফিট (দ্বিতীয় মন্তব্য)
ক্রিস

1
@ ক্রিস আমি উপরের মন্তব্যে প্রতি সমস্যাগুলি সমাধানের জন্য কোড আপডেট করেছি।
রায়ান শুমাচর

আপনার 'ব্যবহার' কোডে আপনি
কমপোসিটারকে কমপোসিটার

7

আপনার কাছে A এবং B অবজেক্টের বিষয়টি বিবেচনা করে একটি খুব সাধারণ সমাধান:

foreach($objB AS $var=>$value){
    $objA->$var = $value;
}

এখানেই শেষ. আপনার এখন অবজেক্টবি থেকে সমস্ত মান সহ আপত্তি আছে।


আপনি কেবল কেন করবেন না: $ objB = $ objA;
স্কটিমেউক

2

\ArrayObjectক্লাসে সম্ভাবনা রয়েছে বিনিময় মূল সংযোগ বিচ্ছিন্ন করতে বর্তমান অ্যারের রেফারেন্স । এটি করার জন্য এটি দুটি কার্যকর পদ্ধতি নিয়ে আসে: exchangeArray()এবং getArrayCopy()। বাকিগুলি জনসাধারণের বৈশিষ্ট্যগুলির array_merge()সাথে সরবরাহিত অবজেক্টের সরল সহজ ArrayObject:

class MergeBase extends ArrayObject
{
     public final function merge( Array $toMerge )
     {
          $this->exchangeArray( array_merge( $this->getArrayCopy(), $toMerge ) );
     }
 }

ব্যবহার এটির মতো সহজ:

 $base = new MergeBase();

 $base[] = 1;
 $base[] = 2;

 $toMerge = [ 3,4,5, ];

 $base->merge( $toMerge );

এটি আসলে গ্রহণযোগ্য উত্তর হওয়া উচিত । একমাত্র সুন্দর জিনিসটি হ'ল যদি merge($array)আসলে অনুরোধও করা হয় \ArrayObject
কায়সার

2

একটি সমাধান সংরক্ষণ করার জন্য, উভয় পদ্ধতি এবং বৈশিষ্ট্যগুলি মার্জড অনজেক্টগুলি থেকে সংযোজনকারী শ্রেণি তৈরি করতে পারে যা তৈরি করতে পারে create

  • __ কনস্ট্রাক্টে যেকোন সংখ্যক অবজেক্ট নিন
  • __call ব্যবহার করে যে কোনও পদ্ধতিতে অ্যাক্সেস করুন
  • __get ব্যবহার করে যে কোনও সম্পত্তি হ্রাস করুন

class combinator{
function __construct(){       
    $this->melt =  array_reverse(func_get_args());
      // array_reverse is to replicate natural overide
}
public function __call($method,$args){
    forEach($this->melt as $o){
        if(method_exists($o, $method)){
            return call_user_func_array([$o,$method], $args);
            //return $o->$method($args);
            }
        }
    }
public function __get($prop){
        foreach($this->melt as $o){
          if(isset($o->$prop))return $o->$prop;
        }
        return 'undefined';
    } 
}

সহজ ব্যবহার

class c1{
    public $pc1='pc1';
    function mc1($a,$b){echo __METHOD__." ".($a+$b);}
}
class c2{
    public $pc2='pc2';
    function mc2(){echo __CLASS__." ".__METHOD__;}
}

$comb=new combinator(new c1, new c2);

$comb->mc1(1,2);
$comb->non_existing_method();  //  silent
echo $comb->pc2;

খুব চালাক, এটি টুপি। আমি মনে করি না যদিও আমি ফলাফলগুলির অবজেক্ট ক্লাসে সংজ্ঞায়িত না হওয়া পদ্ধতিগুলির সাথে স্বাচ্ছন্দ্যবোধ করব।
স্লিথেরিন

ধন্যবাদ? .. টুপিটির জন্য ... এটি কেবল মজাদার জন্য ছিল এবং
নেটবিন

1

আমি দ্বিতীয় অবজেক্টটিকে প্রথম অবজেক্টের একটি প্রোপার্টিটির সাথে সংযুক্ত করে যেতে চাই। যদি দ্বিতীয় বস্তু কোনও ফাংশন বা পদ্ধতির ফলাফল হয় তবে রেফারেন্স ব্যবহার করুন। উদা:

//Not the result of a method
$obj1->extra = new Class2();

//The result of a method, for instance a factory class
$obj1->extra =& Factory::getInstance('Class2');

1

যে কোনও সংখ্যক কাঁচা বস্তু একীভূত করতে

function merge_obj(){
    foreach(func_get_args() as $a){
        $objects[]=(array)$a;
    }
    return (object)call_user_func_array('array_merge', $objects);
}

0

এখানে একটি ফাংশন যা কোনও বস্তু বা অ্যারের সমতল করবে। আপনার কীগুলি অনন্য বলে নিশ্চিত হলেই এটি ব্যবহার করুন। যদি একই নামের কী থাকে তবে সেগুলি ওভাররাইট করা হবে। আপনার এটি একটি শ্রেণিতে স্থাপন এবং আপনার শ্রেণীর নামের সাথে "ফাংশন" প্রতিস্থাপন করতে হবে। উপভোগ করুন ...

function flatten($array, $preserve_keys=1, &$out = array(), $isobject=0) {
        # Flatten a multidimensional array to one dimension, optionally preserving keys.
        #
        # $array - the array to flatten
        # $preserve_keys - 0 (default) to not preserve keys, 1 to preserve string keys only, 2 to preserve all keys
        # $out - internal use argument for recursion
        # $isobject - is internally set in order to remember if we're using an object or array
        if(is_array($array) || $isobject==1)
        foreach($array as $key => $child)
            if(is_array($child))
                $out = Functions::flatten($child, $preserve_keys, $out, 1); // replace "Functions" with the name of your class
            elseif($preserve_keys + is_string($key) > 1)
                $out[$key] = $child;
            else
                $out[] = $child;

        if(is_object($array) || $isobject==2)
        if(!is_object($out)){$out = new stdClass();}
        foreach($array as $key => $child)
            if(is_object($child))
                $out = Functions::flatten($child, $preserve_keys, $out, 2); // replace "Functions" with the name of your class
            elseif($preserve_keys + is_string($key) > 1)
                $out->$key = $child;
            else
                $out = $child;

        return $out;
}

0

আসুন এটি সহজ রাখা যাক!

function copy_properties($from, $to, $fields = null) {
    // copies properties/elements (overwrites duplicates)
    // can take arrays or objects 
    // if fields is set (an array), will only copy keys listed in that array
    // returns $to with the added/replaced properties/keys
    $from_array = is_array($from) ? $from : get_object_vars($from);
    foreach($from_array as $key => $val) {
        if(!is_array($fields) or in_array($key, $fields)) {
            if(is_object($to)) {
                $to->$key = $val;
            } else {
                $to[$key] = $val;
            }
        }
    }
    return($to);
}

যদি এটি আপনার প্রশ্নের উত্তর না দেয় তবে তা অবশ্যই উত্তরের দিকে সাহায্য করবে। উপরের কোডটির ক্রেডিট আমার কাছে যায় :)


0

কোডের এই স্নিপেটটি বারে বারে নেস্টেড ফোরচ লুপগুলি ছাড়াই সেই ডেটাটিকে একক প্রকারের (অ্যারে বা অবজেক্ট) রূপান্তর করবে। আশা করি এটি কাউকে সাহায্য করবে!

একবার যখন কোনও বস্তু অ্যারে বিন্যাসে আসবে আপনি অ্যারে_মেজ ব্যবহার করতে পারেন এবং আপনার প্রয়োজন হলে আবার অবজেক্টে রূপান্তর করতে পারেন।

abstract class Util {
    public static function object_to_array($d) {
        if (is_object($d))
            $d = get_object_vars($d);

        return is_array($d) ? array_map(__METHOD__, $d) : $d;
    }

    public static function array_to_object($d) {
        return is_array($d) ? (object) array_map(__METHOD__, $d) : $d;
    }
}

পদ্ধতিগত উপায়

function object_to_array($d) {
    if (is_object($d))
        $d = get_object_vars($d);

    return is_array($d) ? array_map(__FUNCTION__, $d) : $d;
}

function array_to_object($d) {
    return is_array($d) ? (object) array_map(__FUNCTION__, $d) : $d;
}

সমস্ত কৃতিত্ব যায়: জেসন ওকলে

আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.