|
404 | 404 | % overloaded assignment operator: handling assignments at arbitrary depths |
405 | 405 | function obj = subsasgn(obj, idxkey, otherobj) |
406 | 406 | % overloading the setter function, obj.('key').('subkey')=otherobj |
407 | | - % expanded from rahnema1's sample at https://stackoverflow.com/a/79030223/4271392 |
408 | 407 |
|
409 | 408 | % handle curly bracket indexing for setting attributes |
410 | 409 | oplen = length(idxkey); |
|
423 | 422 | if (iscell(idxkey(oplen).subs) && ~isempty(idxkey(oplen).subs)) |
424 | 423 | attrn = idxkey(oplen).subs{1}; |
425 | 424 | if (ischar(attrn)) |
426 | | - % Build the path by navigating through keys |
427 | 425 | temppath = obj.currentpath__; |
428 | 426 | for i = 1:oplen - 1 |
429 | 427 | idx = idxkey(i); |
|
443 | 441 | end |
444 | 442 | end |
445 | 443 | end |
446 | | - % set attribute on original object with computed path |
447 | 444 | obj.setattr(temppath, attrn, otherobj); |
448 | 445 | return |
449 | 446 | end |
|
454 | 451 | if (oplen >= 2 && strcmp(idxkey(oplen).type, '()')) |
455 | 452 | if (strcmp(idxkey(oplen - 1).type, '.') && ischar(idxkey(oplen - 1).subs)) |
456 | 453 | dimname = idxkey(oplen - 1).subs; |
457 | | - % build path to the data |
458 | 454 | temppath = obj.currentpath__; |
459 | 455 | for i = 1:oplen - 2 |
460 | 456 | idx = idxkey(i); |
|
474 | 470 | end |
475 | 471 | end |
476 | 472 | end |
477 | | - % check if dimname is in dims |
478 | 473 | dims = obj.getattr(temppath, 'dims'); |
479 | 474 | if (~isempty(dims) && iscell(dims)) |
480 | 475 | dimpos = find(strcmp(dims, dimname)); |
481 | 476 | if (~isempty(dimpos) && ~isempty(idxkey(oplen).subs)) |
482 | | - % build full indices |
483 | 477 | nddata = length(dims); |
484 | 478 | indices = repmat({':'}, 1, nddata); |
485 | 479 | indices{dimpos(1)} = idxkey(oplen).subs{1}; |
486 | | - % perform assignment |
487 | 480 | subsargs = struct('type', '()', 'subs', {indices}); |
488 | 481 | if (oplen > 2) |
489 | | - % need to assign back through the chain |
490 | 482 | subidx = idxkey(1:oplen - 2); |
491 | 483 | tempdata = subsref(obj.data, subidx); |
492 | 484 | tempdata = subsasgn(tempdata, subsargs, otherobj); |
|
503 | 495 | % Fast path: single-level assignment like jd.key = value |
504 | 496 | if (oplen == 1 && strcmp(idxkey(1).type, '.') && ischar(idxkey(1).subs)) |
505 | 497 | fieldname = idxkey(1).subs; |
506 | | - % Skip if JSONPath |
507 | 498 | if (isempty(fieldname) || fieldname(1) ~= char(36)) |
508 | 499 | if (isempty(obj.data)) |
509 | 500 | obj.data = struct(); |
|
513 | 504 | obj.data.(fieldname) = otherobj; |
514 | 505 | return |
515 | 506 | catch |
516 | | - % Field name invalid for struct, convert to Map |
517 | 507 | fnames = fieldnames(obj.data); |
518 | 508 | if (~isempty(fnames)) |
519 | 509 | obj.data = containers.Map(fnames, struct2cell(obj.data), 'UniformValues', 0); |
|
530 | 520 | end |
531 | 521 | end |
532 | 522 |
|
| 523 | + % Fast path: single numeric index like jd.(1) = value |
| 524 | + if (oplen == 1 && strcmp(idxkey(1).type, '.') && isnumeric(idxkey(1).subs)) |
| 525 | + newidx = idxkey(1).subs; |
| 526 | + if isstruct(obj.data) && isstruct(otherobj) |
| 527 | + fnames = fieldnames(obj.data); |
| 528 | + if isempty(fnames) || numel(obj.data) == 0 |
| 529 | + objfnames = fieldnames(otherobj); |
| 530 | + if newidx == 1 |
| 531 | + obj.data = otherobj; |
| 532 | + else |
| 533 | + for fi = 1:length(objfnames) |
| 534 | + obj.data(newidx).(objfnames{fi}) = otherobj.(objfnames{fi}); |
| 535 | + end |
| 536 | + end |
| 537 | + else |
| 538 | + if newidx > numel(obj.data) |
| 539 | + for fi = 1:length(fnames) |
| 540 | + obj.data(newidx).(fnames{fi}) = []; |
| 541 | + end |
| 542 | + end |
| 543 | + reordered = struct(); |
| 544 | + for fi = 1:length(fnames) |
| 545 | + if isfield(otherobj, fnames{fi}) |
| 546 | + reordered.(fnames{fi}) = otherobj.(fnames{fi}); |
| 547 | + else |
| 548 | + reordered.(fnames{fi}) = []; |
| 549 | + end |
| 550 | + end |
| 551 | + obj.data(newidx) = reordered; |
| 552 | + end |
| 553 | + elseif iscell(obj.data) |
| 554 | + obj.data{newidx} = otherobj; |
| 555 | + else |
| 556 | + obj.data(newidx) = otherobj; |
| 557 | + end |
| 558 | + return |
| 559 | + end |
| 560 | + |
533 | 561 | oplen = length(idxkey); |
534 | | - opcell = cell (1, oplen + 1); |
| 562 | + opcell = cell(1, oplen + 1); |
535 | 563 | if (isempty(obj.data)) |
536 | 564 | obj.data = obj.newkey_(); |
537 | 565 | end |
|
540 | 568 | for i = 1:oplen |
541 | 569 | idx = idxkey(i); |
542 | 570 | if (strcmp(idx.type, '.')) |
| 571 | + % Handle numeric indexing: person.(1), person.(2), etc. |
| 572 | + if isnumeric(idx.subs) |
| 573 | + newidx = idx.subs; |
| 574 | + if isstruct(opcell{i}) && isscalar(newidx) && newidx > numel(opcell{i}) |
| 575 | + fnames = fieldnames(opcell{i}); |
| 576 | + for fi = 1:length(fnames) |
| 577 | + opcell{i}(newidx).(fnames{fi}) = []; |
| 578 | + end |
| 579 | + elseif iscell(opcell{i}) && isscalar(newidx) && newidx > numel(opcell{i}) |
| 580 | + opcell{i}{newidx} = []; |
| 581 | + end |
| 582 | + if iscell(opcell{i}) |
| 583 | + opcell{i + 1} = opcell{i}{newidx}; |
| 584 | + else |
| 585 | + opcell{i + 1} = opcell{i}(newidx); |
| 586 | + end |
| 587 | + continue |
| 588 | + end |
543 | 589 | if (ischar(idx.subs) && strcmp(idx.subs, 'v') && i < oplen && strcmp(idxkey(i + 1).type, '()')) |
544 | 590 | opcell{i + 1} = opcell{i}; |
545 | 591 | if (i < oplen && iscell(opcell{i})) |
|
548 | 594 | continue |
549 | 595 | end |
550 | 596 | if (ischar(idx.subs) && ~(~isempty(idx.subs) && idx.subs(1) == char(36))) |
551 | | - % Handle empty or non-struct/map data |
552 | 597 | if isempty(opcell{i}) || (~isstruct(opcell{i}) && ~ismap_(obj.flags__, opcell{i})) |
553 | 598 | opcell{i} = obj.newkey_(); |
554 | 599 | end |
|
604 | 649 | idx.type = '()'; |
605 | 650 | end |
606 | 651 |
|
| 652 | + % Handle numeric indexing in backward loop |
| 653 | + if (strcmp(idx.type, '.') && isnumeric(idx.subs)) |
| 654 | + newidx = idx.subs; |
| 655 | + if iscell(opcell{i}) |
| 656 | + opcell{i}{newidx} = opcell{i + 1}; |
| 657 | + else |
| 658 | + opcell{i}(newidx) = opcell{i + 1}; |
| 659 | + end |
| 660 | + continue |
| 661 | + end |
| 662 | + |
607 | 663 | if (ischar(idx.subs) && strcmp(idx.subs, 'v') && i < oplen && ismember(idxkey(i + 1).type, {'()', '{}'})) |
608 | 664 | opcell{i} = opcell{i + 1}; |
609 | 665 | continue |
|
615 | 671 | else |
616 | 672 | opcell{i} = opcell{i + 1}; |
617 | 673 | end |
618 | | - i = i - 1; |
619 | 674 | elseif (ischar(idx.subs) && ~isempty(idx.subs) && idx.subs(1) == char(36)) |
620 | 675 | opcell{i} = obj.call_('jsonpath', opcell{i}, idx.subs, opcell{i + 1}); |
621 | 676 | else |
|
0 commit comments