Juggling with multiple objects

This question is coded in pseudo-PHP, but I really don't mind which language I get the answers in (with the exception of Ruby: -P) as this is purely hypothetical. In fact, PHP is arguably the worst language for this type of logic. Unfortunately, I have never done this before, so I cannot provide a real world example. Therefore, hypothetical answers are perfectly acceptable.

Basically I have a lot of objects doing the task. For this example, let's assume each object is a class that downloads a file from the Internet. Each object will download a different file and the download is done in parallel. Obviously, some objects may finish loading before others. The actual data capture can be done in streams, but that is not relevant to this question.

So, we can define an object as such:

class DownloaderObject() {
    var $url = '';
    var $downloading = false;

    function DownloaderObject($v){ // constructor
        $this->url = $v;
        start_downloading_in_the_background(url=$this->$url, callback=$this->finished);
        $this->downloading = true;
    }

    function finished() {
        save_the_data_somewhere();
        $this->downloading = false;
        $this->destroy(); // actually destroys the object
    }
}

      

So, we have many objects like this:

$download1 = new DownloaderObject('http://somesite.com/latest_windows.iso');
$download2 = new DownloaderObject('http://somesite.com/kitchen_sink.iso');
$download3 = new DownloaderObject('http://somesite.com/heroes_part_1.rar');

      

And we can store them in an array:

$downloads = array($download1, $download2, $download3);

      

So we have an array full of downloads:

array(
  1 => $download1,
  2 => $download2,
  3 => $download3
)

      

And we can go through them like this:

print('Here are the downloads that are running:');
foreach ($downloads as $d) {
    print($d->url . "\n");
}

      

Ok, now suppose download 2 is complete and the object is destroyed. We should now have two objects in the array:

array(
  1 => $download1,
  3 => $download3
)

      

But there is a hole in the array! Key # 2 is not used. Also, if I wanted to start a new download, it is not clear where to insert the download into the array. The following might work:

$i = 0;
while ($i < count($downloads) - 1) {
    if (!is_object($downloads[$i])) {
        $downloads[$i] = new DownloaderObject('http://somesite.com/doctorwho.iso');
        break;
    }
    $i++;
}

      

However, this is terribly inefficient (and while $i++

loops are nooby). So, another approach is to keep a counter.

function add_download($url) {
    global $downloads;
    static $download_counter;

    $download_counter++;
    $downloads[$download_counter] = new DownloaderObject($url);
}

      

This will work, but we still get holes in the array:

array(
  1  => DownloaderObject,
  3  => DownloaderObject,
  7  => DownloaderObject,
  13 => DownloaderObject
)

      

It's ugly. However, is this acceptable? Should the array be "defragmented", i.e. Keys rearranged to close gaps?

Or is there another programming structure I should be aware of? I want a structure that I can add stuff to, remove stuff, access keys in a variable, loop through, etc. that is not an array. Is there such a thing?

I've been coded for years, but this question has been bugging me for so many of those years and I still don't know the answer. This may be obvious to some programmers, but for me it is completely non-trivial.

0


source to share


6 answers


Some good answers to this question that reflect the relative experiences of the respondents. Thank you so much - they turned out to be very educational.

I posted this question almost three years ago. Looking back, I see that my knowledge in this area is severely lacking. The biggest problem I was experiencing was that I was coming from a PHP perspective, which does not have the ability to randomly pop elements. Something else in answering this question helped me discover that the fundamentally improved model is "linked lists" .

For C, I wrote a post on linked lists that contains code samples (too many to post here), but carefully fill in the original question used case.



For PHP, the linked list implementation appears here , which I have never tried, but imagine this would also be the correct way with the above.

Interestingly, Python lists contain a method pop()

that, unlike PHP array_pop()

, can call arbitrary elements and keep everything in order. For example:

>>> x = ['baa', 'ram', 'ewe'] # our starting point
>>> x[1]                      # making sure element 1 is 'ram'
'ram'
>>> x.pop(1)                  # let arbitrarily pop an element in the middle
'ram'
>>> x                         # the one we popped ('ram') is now gone
['baa', 'ewe']
>>> x[1]                      # and there are no holes: item 2 has become item 1
'ewe'

      

0


source


The problem with PHP "associative arrays" is that they are not arrays at all, they are Hashmaps . With holes, everything is fine. You can look at the linked list , but Hashmap seems to be great for what you are doing.



+4


source


What does your loader array support?

If you encapsulate the array into a class that has been notified by the loader when it is finished, you don't have to worry about obsolete references to destroyed objects.

This class can manage the organization of an array internally and provide an interface to its users that looks more like an iterator than an array.

+2


source


"$ i ++ loops" are nooby, but only because the code becomes much clearer if you use a for loop:

$i = 0;
while ($i < count($downloads) - 1) {
    if (!is_object($downloads[$i])) {
       $downloads[$i] = new DownloaderObject('http://somesite.com/doctorwho.iso');
        break;
    }
    $i++;
}

      

becomes

for($i=0;$i<count($downloads)-1;++$i){
    if (!is_object($downloads[$i])) {
        $downloads[$i] = new DownloaderObject('http://somesite.com/doctorwho.iso');
        break;
    }
}

      

+1


source


From a C # perspective, I thought you needed a different data structure for the array - you need to think about the problem using a higher level data structure. Perhaps Queue, List, or Stack are better for your purposes?

+1


source


The short answer to your question is that in PHP, arrays are used for almost everyone and you rarely end up using other data structures. Having holes in array indexes is nothing to worry about. In other programming languages, such as Java, you have a more diverse set of data structures to choose from: sets, hashes, lists, vectors, and more. It looks like you also need closer interaction between the Array class and the DownloaderObject. Just because the $ download2 object has "destroy ()", the array will maintain a reference to that object.

+1


source







All Articles