การสร้าง MATLAB ของ struct-vector

ให้ข้อมูลบางอย่าง - ตัวอย่างเช่น (ในกรณีของฉัน) - เหมือนตารางต่อไปนี้

Name  |pos_x|pos_y|pos_z
------------------------
Point1|   .1|   .1|   .2
Point2|  0.0|  0.0|   .1
Middle|   .1|   .2|   .1
Point3|  0.0|    1|  0.0

และบางทีหลังจากการนำเข้าข้อมูลจาก Excel ค่าทั้งหมดจะถูกเก็บไว้ในอาร์เรย์เซลล์ (ขอเรียกมันว่า celldata)
เพื่อวัตถุประสงค์ในการทดสอบเซลล์นี้สามารถสร้างขึ้นด้วยบรรทัด

celldata={'Point1' .1 .1 .2;'Point2' 0 0 .1;'Middle' .1 .2 .1;'Point3' 0 1 0}

สำหรับตัวอย่างนี้ เซลล์มีขนาด 4x4

ในขณะนี้ ฉันกำลังสร้างโครงสร้างด้วยบรรทัดต่อไปนี้

point.name=char(celldata(:,1));
point.posxyz=cell2mat(celldata(:,2:4));

ผลลัพธ์ที่ได้คือ point size 1x1 Class struct ฉันกำลังมองหาวิธีที่มีประสิทธิภาพในการสร้างมันเป็น point size 4x1 Class struct - ดังนั้นหนึ่งองค์ประกอบสำหรับแต่ละบรรทัดในตารางด้านบน - ทั้งหมดนี้มีโครงสร้างภายในเหมือนกัน: ชื่อและพิกัด
ฉันลองแล้ว cell2struct แต่นั่นเป็นเพียงเท่านั้น สามารถขยายออกไปในมิติเดียวโดยไม่ต้องจัดกลุ่มบางคอลัมน์เข้าด้วยกัน - เท่าที่ฉันได้ลอง
นอกจากนี้ นี่ยังไม่ซ้ำกับ จัดสรรโครงสร้างเซลล์ล่วงหน้าใน Matlab ในกรณีนี้ ฉันมีคอลัมน์ที่แตกต่างกันมากมาย - หรืออาจเป็นจำนวนคอลัมน์แบบไดนามิกด้วยซ้ำ


person Bastian Ebeling    schedule 29.04.2013    source แหล่งที่มา
comment
คุณคิดว่า dataset จะมีประโยชน์ใดๆ หรือไม่?   -  person fpe    schedule 29.04.2013
comment
ฉันคิดว่ามันคงจะดีสำหรับการวนซ้ำองค์ประกอบ: for punkt=point,disp([punkt.name ':' num2str(norm(punkt.posxyz))]),end เป็นตัวอย่าง โดยเฉพาะอย่างยิ่งเราไม่จำเป็นต้องตรวจสอบว่ามีองค์ประกอบกี่รายการ คุณรู้อะไรดีขึ้นบ้างไหม?   -  person Bastian Ebeling    schedule 29.04.2013


คำตอบ (2)


cellData = {'Name', 'pos_x', 'pos_y'; 'Harry', 34, 2; 'Bernard', 5, 11}

แล้ว

for col = 1:size(cellData ,2)
    fieldName = cellData{1, col};
    c = cellData (2:end, col);
    [point(1:length(c)).(fieldName)] = c{:};
end

ตอนนี้

point(1)

ans = 

     Name: 'Harry'
    pos_x: 34
    pos_y: 2

point(2)

ans = 

     Name: 'Bernard'
    pos_x: 5
    pos_y: 11

แก้ไข:

หากคุณต้องการมีเพียง 2 ฟิลด์ นั่นคือ Name และ posxyz ดังนั้น:

 [M, N] = size(celldata);
 names = celldata(:,1);
 [point(1:M).Name] = names{:};
 xyz = mat2cell(cell2mat(celldata(:,2:end)), ones(M,1), N - 1);
 [point(1:M).posxyz] = xyz{:};

ตอนนี้สำหรับ celldata={'Point1' .1 .1 .2;'Point2' 0 0 .1;'Middle' .1 .2 .1;'Point3' 0 1 0}

point(1)

ans = 

          Name: 'Point1'
        posxyz: [0.1000 0.1000 0.2000]

point(2)

ans = 

      Name: 'Point2'
    posxyz: [0 0 0.1000]
person Dan    schedule 29.04.2013
comment
ขอบคุณ @Dan สำหรับแนวคิดนี้ แต่ฉันไม่ชอบความจำเป็นในการกำหนดชื่อ (ตัวอย่าง) ทีละชื่อ โปรดคิดถึงตารางที่มีหลายร้อยบรรทัดขึ้นไป ความคิดเพิ่มเติม? - person Bastian Ebeling; 29.04.2013
comment
แน่นอนว่าการเพิ่มสามารถทำได้เหมือนที่ทำภายใน rmfield.m - แต่ฉันคิดว่านี่ควรจะเป็นไปได้เร็วกว่านี้หรือเปล่า - person Bastian Ebeling; 29.04.2013
comment
@BastianEbeling หลายร้อยบรรทัดหรือหลายร้อยคอลัมน์? - person Dan; 29.04.2013
comment
สวัสดี Dan ในความคิดเห็นของฉันฉันพูดถึงหลายร้อยบรรทัด แต่ (เหมือนในการแก้ไขครั้งล่าสุดของฉัน ซึ่งคุณอาจไม่เคยเห็นมาก่อน) อาจมีหลายคอลัมน์ก็ได้ - person Bastian Ebeling; 29.04.2013
comment
@BastianEbeling เห็นได้ชัดว่าบรรทัดไม่ใช่ปัญหา เพียงแทนที่ 4 ด้วย length(C) สำหรับคอลัมน์ ฉันคิดว่าทางออกที่ดีที่สุดของคุณคือ for loop แบบง่าย ดังนั้นหาก col เป็นตัวแปร loop และ C = celldata{:, col} แล้ว [point(1:length(C), col).(C{1})] = C{2:end} - person Dan; 29.04.2013
comment
ภายในการเขียนโปรแกรมของฉัน ฉันมักจะพยายามป้องกันการใช้ for loops ในบรรทัดของฉันด้านบน ไม่จำเป็นต้องมี for-loop หรือการตรวจสอบความยาว ตัวอย่างสุดท้ายของคอลัมน์ไม่ทำงานภายใน R2013a - person Bastian Ebeling; 29.04.2013
comment
ให้เราสนทนาต่อในการแชท - person Bastian Ebeling; 29.04.2013

ลองใช้ struct โดยมีอาร์เรย์เซลล์เป็นอินพุต:

C = cellfun(@(x,y,z)[x y z], celldata(:,2), celldata(:,3), celldata(:,4), 'Uniform', 0);
point = struct('name', celldata(:, 1), 'posxyz', C);

โปรดสังเกตว่าสำหรับฟิลด์ posxyz ฉันได้สร้างอาร์เรย์เซลล์ใหม่โดยการแบ่งเซลล์ของ celldata

หากคุณต้องการเพิ่มช่องอื่นในภายหลัง คุณสามารถใช้ deal และ รายการที่คั่นด้วยเครื่องหมายจุลภาค ตัวอย่างต่อไปนี้เก็บค่าจากคอลัมน์ที่สี่ของ celldata ไว้ในฟิลด์ใหม่ที่เรียกว่า pos_z:

[point(:).pos_z] = deal(celldata{:, 4});
person Eitan T    schedule 29.04.2013
comment
ขอบคุณครับ นี่เป็นความคิดที่ดีจริงๆ ในกรณีของฉัน มีคอลัมน์อื่นๆ อีกมากมาย และเพื่อให้สามารถอ่านได้ง่าย ฉันต้องการเพิ่มแต่ละคอลัมน์ (หรือคู่ของคอลัมน์ เช่น ใน xyz) ในบรรทัดซอร์สโค้ดบรรทัดเดียว คุณรู้วิธีเพิ่มฟิลด์ให้กับโครงสร้างจุดที่คุณสร้างขึ้นหรือไม่? - person Bastian Ebeling; 29.04.2013
comment
@BastianEbeling แน่นอน คุณจะต้องใช้ deal และ รายการที่คั่นด้วยเครื่องหมายจุลภาค ดูคำตอบที่แก้ไขแล้ว - person Eitan T; 29.04.2013