1

I’m working with large nested associative arrays in PHP and I need to apply transformations (like map, filter, reshape) immutably, meaning the original array should not be modified.

The problem is that every time I use array_map or array_filter, PHP creates a new array copy, which becomes very slow and memory-heavy for large datasets.

For example:

 $data = [
'users' => [
 ['id' => 1, 'name' => 'Alice', 'active' => true],
 ['id' => 2, 'name' => 'Bob', 'active' => false],
]];
$mapped = array_map(fn($u) => ['id' => $u['id']], $data['users']);
$filtered = array_filter($mapped, fn($u) => $u['id'] % 2 === 0);

This works but copies arrays multiple times. On large inputs, it’s slow and inefficient.

Main question: What is the most efficient way in PHP to transform nested arrays immutably without repeatedly creating deep copies?

KIKO Software
17.3k3 gold badges33 silver badges53 bronze badges
asked Sep 7 at 11:12
4
  • 3
    This sounds like a good task to use a database. Commented Sep 7 at 12:18
  • You might want to look at other questions like stackoverflow.com/questions/5792388/… Commented Sep 7 at 14:43
  • 1
    I would urge you to filter before bothering to restructure the data because otherwise you are going to process some data sets before you throw them away. Are we looking at a realistic process in your question, or does it get crazy-convoluted? Commented Sep 8 at 4:34
  • Arrrays in php are always copied when passed or returned, while objects are always passed by reference. It's not enough information here but I think that if you don't need all the data you can use transducers, streams, generators and if you need all the data some kind of data structure that works like an array, but is really an object that is layered such that for each iteration you make a new instance with the old as "fallback" and fetching will only update when the original data is changed... More complex than the other alternatives. Commented Sep 8 at 13:48

2 Answers 2

2

As mentioned in the comments section, one option would be the use of generators, that will basically iterate "on-demand". Also, use references (&) instead of values.

Example:


$data = [
 'users' => [
 ['id' => 1, 'name' => 'Alice', 'active' => true],
 ['id' => 2, 'name' => 'Bob', 'active' => false], 
 ]
];
$filterPairIds = function() use (&$data) {
 foreach ($data['users'] as &$user) {
 if ($user['id'] % 2 === 0) {
 yield $user;
 }
 }
};
$filtered = $filterPairIds();
foreach ($filtered as $user) {
 print_r($user);
} 

This should optimize memory usage.

Example link (php sandbox): https://onlinephp.io/c/c79a7

answered Sep 8 at 16:48
Sign up to request clarification or add additional context in comments.

Comments

2

You might want to consider classic PHP programming:

$data = ['users' => [
 ['id' => 1, 'name' => 'Alice', 'active' => true],
 ['id' => 2, 'name' => 'Bob', 'active' => false],
]];
$filtered = [];
foreach ($data['users'] as $key => $user) {
 if ($user['id'] % 2 === 0) {
 $filtered[$key] = ['id' => $user['id']];
 }
}
var_export($filtered);

Output:

array (
 1 => 
 array (
 'id' => 2,
 ),
)

This shouldn't be hard to read when you're used to PHP. Each user is processed separately, and only added to the final output when all processing is done. That means it doesn't create copies of big arrays, it's efficient. Some people thing that using build-in functions would more efficient, but there's no real reason to think so in this case. Quite the opposite.

Demo: https://3v4l.org/KXYnC

answered Sep 8 at 17:48

Comments

Your Answer

Draft saved
Draft discarded

Sign up or log in

Sign up using Google
Sign up using Email and Password

Post as a guest

Required, but never shown

Post as a guest

Required, but never shown

By clicking "Post Your Answer", you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.