Solidity中如何获取特定地址对应映射内的全部结构体
嘿,我来帮你搞定这个问题!你的代码里getOverview函数只返回第一个处方的原因很简单——循环里找到第一个匹配的记录就直接return了,程序直接退出循环,自然拿不到所有结果。
关于你问的数组索引计数器:完全不需要额外在Prescription结构体里存index_counter变量哦!因为ownerOfPrescription[patient]本身就是一个动态数组,它自带的length属性可以直接用来遍历,循环里的i就是天然的索引计数器,直接用它访问数组元素就好。
接下来给你调整后的代码,让getOverview返回该地址下的所有处方参数:
pragma solidity ^0.4.17; contract Prescribe { struct Prescription { address patients_address; string medicament; string dosage_form; uint amount; uint date; // 不需要额外的index_counter } mapping (address => Prescription[]) public ownerOfPrescription; address [] public patients; // 这里假设你已经定义了restricted修饰符,比如用于权限控制 modifier restricted() { // 你的权限逻辑,比如只有指定角色可以调用 _; } function createPrescription(address patients_address, string medicament, string dosage_form, uint amount, uint date) public restricted { ownerOfPrescription[patients_address].push(Prescription({ patients_address: patients_address, medicament: medicament, dosage_form: dosage_form, amount: amount, date: date })); patients.push(patients_address); } function getOverview(address patient) public view restricted returns(string[] memory, string[] memory, uint[] memory, uint[] memory) { // 先根据处方数量初始化返回数组的长度 uint prescCount = ownerOfPrescription[patient].length; string[] memory medicaments = new string[](prescCount); string[] memory dosageForms = new string[](prescCount); uint[] memory amounts = new uint[](prescCount); uint[] memory dates = new uint[](prescCount); for(uint i = 0; i < prescCount; i++) { // 用storage引用当前处方,节省gas开销 Prescription storage currentPresc = ownerOfPrescription[patient][i]; // 因为mapping是按patient地址关联的,所以这里的patients_address必然等于传入的patient,无需判断 medicaments[i] = currentPresc.medicament; dosageForms[i] = currentPresc.dosage_form; amounts[i] = currentPresc.amount; dates[i] = currentPresc.date; } return(medicaments, dosageForms, amounts, dates); } }
几点关键说明:
- 调整了
getOverview的返回类型:改成返回四个数组,分别对应所有处方的药品名称、剂型、数量和日期——因为Solidity 0.4.17版本还不支持直接返回结构体数组,所以用这种方式批量返回数据。 - 去掉了多余的
if判断:ownerOfPrescription是通过患者地址映射的数组,数组内的每个处方的patients_address必然等于传入的patient参数,这个判断完全没必要,去掉还能节省gas。 - 用
storage引用当前处方:避免每次循环都拷贝结构体数据,提升合约执行效率。
另外提个小细节:你的patients数组每次调用createPrescription都会push患者地址,如果多次给同一患者开处方,会产生重复数据。如果需要维护唯一的患者列表,可以在push前判断地址是否已存在,但这属于额外优化,不影响当前核心需求。
内容的提问来源于stack exchange,提问作者Seyhan Ilhan
相关产品推荐
相关产品推荐

