Что некоторые эффективные пути состоят в том, чтобы объединить две структуры в MATLAB?

PECS (сокращение от «Производитель extends и Consumer super») объясняется: принципом «Get and Put»

«Get And Put» (из Java Generics and Collections)

Указывает, что

  1. использует расширенный подстановочный знак, когда вы получаете только значения из структуры
  2. , используя суперсимвол, когда вы добавляете значения только в структуру
  3. и не использовать подстановочный знак, когда вы оба получаете и ставите.

Давайте рассмотрим его на примере:

1. For Extends Wildcard (получить значения, т. Е. Producer extends)

Вот метод, который берет набор чисел, преобразует каждый в double и суммирует их вверх

public static double sum(Collection<? extends Number> nums) {
   double s = 0.0;
   for (Number num : nums) 
      s += num.doubleValue();
   return s;
}

Назовем метод:

List<Integer>ints = Arrays.asList(1,2,3);
assert sum(ints) == 6.0;
List<Double>doubles = Arrays.asList(2.78,3.14);
assert sum(doubles) == 5.92;
List<Number>nums = Arrays.<Number>asList(1,2,2.78,3.14);
assert sum(nums) == 8.92;

Поскольку метод sum() использует extends, все следующие вызовы являются законными. Первые два вызова не были бы законными, если бы расширения не использовались.

ИСКЛЮЧЕНИЕ : вы не можете помещать что-либо в тип, объявленный с помощью подстановочного знака extends, за исключением значения null, который относится к каждому ссылочному типу:

List<Integer> ints = new ArrayList<Integer>();
ints.add(1);
ints.add(2);
List<? extends Number> nums = ints;
nums.add(null);  // ok
assert nums.toString().equals("[1, 2, null]");

2. Для Super Wildcard (put values ​​ie Consumer super)

Вот метод, который принимает набор чисел и int n, и помещает первые n целые числа, начиная с нуля, в сбор:

public static void count(Collection<? super Integer> ints, int n) {
    for (int i = 0; i < n; i++) ints.add(i);
}

Давайте назовем метод:

List<Integer>ints = new ArrayList<Integer>();
count(ints, 5);
assert ints.toString().equals("[0, 1, 2, 3, 4]");
List<Number>nums = new ArrayList<Number>();
count(nums, 5); nums.add(5.0);
assert nums.toString().equals("[0, 1, 2, 3, 4, 5.0]");
List<Object>objs = new ArrayList<Object>();
count(objs, 5); objs.add("five");
assert objs.toString().equals("[0, 1, 2, 3, 4, five]");

Поскольку метод count() использует super, все следующие звонки законны: последние два вызова не были бы законными, если бы супер не использовался.

ИСКЛЮЧЕНИЕ : вы не можете получить что-либо из типа, объявленного с помощью super за исключением значения типа Object, которое является супертипом каждого ссылочного типа:

List<Object> objs = Arrays.<Object>asList(1,"two");
List<? super Integer> ints = objs;
String str = "";
for (Object obj : ints) str += obj.toString();
assert str.equals("1two");

3. Когда оба Get и Put, не используйте wildcard

. Когда вы оба вставляете значения и получаете значения из одной и той же структуры, вы не должны использовать подстановочный знак.

public static double sumCount(Collection<Number> nums, int n) {
   count(nums, n);
   return sum(nums);
}
24
задан gnovice 21 September 2010 в 02:58
поделиться

4 ответа

Без коллизий можно сделать

M = [fieldnames(A)' fieldnames(B)'; struct2cell(A)' struct2cell(B)'];
C=struct(M{:});

, И это довольно эффективно. Однако struct ошибки на дублирующихся именах полей, и предварительно проверяющий на них использующий unique уничтожают производительность до такой степени, что цикл лучше. Но вот то, на что это было бы похоже:

M = [fieldnames(A)' fieldnames(B)'; struct2cell(A)' struct2cell(B)'];

[tmp, rows] = unique(M(1,:), 'last');
M=M(:, rows);

C=struct(M{:});

Вы могли бы быть в состоянии сделать гибридное решение, не принимая конфликтов и используя попытку/выгоду вокруг вызова к struct для корректного ухудшения к случаю обработки конфликта.

19
ответ дан SCFrench 28 November 2019 в 23:42
поделиться

Я нашел хорошее решение для обмена файлами: catstruct .

Без тестирования производительности могу сказать, что он сделал именно то, что хотел. Конечно, он может работать с дублирующимися полями.

Вот как это работает:

a.f1 = 1;
a.f2 = 2;
b.f2 = 3;
b.f4 = 4;

s = catstruct(a,b)

даст

s = 

    f1: 1
    f2: 3
    f3: 4
5
ответ дан Dennis Jaheruddin 28 November 2019 в 23:42
поделиться

Я не думаю, что вы можете справиться с конфликтами без петель, и я не думаю, что вам нужно их избегать. (хотя я полагаю, что эффективность может быть проблемой со многими областями ...)

Я использую функцию, которую я написал несколько лет назад, под названием setdefaults.m, которая объединяет одну структуру со значениями другой структуры, где один имеет приоритет над другим в случае конфликта.

% SETDEFAULTS sets the default structure values 
%    SOUT = SETDEFAULTS(S, SDEF) reproduces in S 
%    all the structure fields, and their values,  that exist in 
%    SDEF that do not exist in S. 
%    SOUT = SETDEFAULTS(S, SDEF, OVERRIDE) does
%    the same function as above, but if OVERRIDE is 1,
%    it copies all fields of SDEF to SOUT.

function sout = setdefaults(s,sdef,override)
if (not(exist('override','var')))
    override = 0;
end

sout = s;
for f = fieldnames(sdef)'
    cf = char(f);
    if (override | not(isfield(sout,cf)))
        sout = setfield(sout,cf,getfield(sdef,cf));
    end
end

Теперь, когда я думаю об этом, я почти уверен, что вход «переопределить» не нужен (вы можете просто изменить порядок входов), хотя я не уверен на 100% в этом ... Итак, вот более простое переписывание (setdefaults2.m):

% SETDEFAULTS2 sets the default structure values 
%    SOUT = SETDEFAULTS(S, SDEF) reproduces in S 
%    all the structure fields, and their values,  that exist in 
%    SDEF that do not exist in S. 

function sout = setdefaults2(s,sdef)
sout = sdef;
for f = fieldnames(s)'
    sout = setfield(sout,f{1},getfield(s,f{1}));
end

и некоторые образцы для его проверки:

>> S1 = struct('a',1,'b',2,'c',3);
>> S2 = struct('b',4,'c',5,'d',6);
>> setdefaults2(S1,S2)

ans = 

    b: 2
    c: 3
    d: 6
    a: 1

>> setdefaults2(S2,S1)

ans = 

    a: 1
    b: 4
    c: 5
    d: 6
4
ответ дан Jason S 28 November 2019 в 23:42
поделиться

В C структура может иметь другую структуру как один из, его - участники. В то время как это не точно то же как, что Вы спрашиваете, Вы могли закончить или с ситуацией, где одна структура содержит другого, или одна структура содержит две структуры, обе из которых содержат части информации, которую Вы хотели.

psuedocode: я не помню фактический синтаксис.

A.field1 = 1;
A.field2 = 'a';
A.field3 = struct B;

для доступа: field3.field4;

или что-то вроде этого.

Или у Вас могла быть структура C, содержат и A и B:

C.A = struct A;
C.B = struct B;

с доступом тогда что-то как

C.A.field1;
C.A.field2;
C.B.field3;
C.B.field4;

надежда это помогает!

РЕДАКТИРОВАНИЕ: оба из этих решений стараются не называть коллизии.

кроме того, я не видел Ваш matlab тег. Условно, необходимо хотеть отредактировать вопрос включать ту часть информации

2
ответ дан pbh101 28 November 2019 в 23:42
поделиться
Другие вопросы по тегам:

Похожие вопросы: