英文:
How to create lists of subdata to loop through in Freemarker
问题
我正在寻找一种使用Freemarker生成按dataType(整数)分组的报告的方法,根据数据项列表。
所以,例如,我有:
data.datatype = 1,其中data的id = 1
data.datatype = 1,其中data的id = 4
data.datatype = 1,其中data的id = 7
data.datatype = 3,其中data的id = 2
data.datatype = 3,其中data的id = 3
data.datatype = 4,其中data的id = 5
...等等
这个序列按数据类型排序,但同时我需要保持数据项按其相应的顺序(次要排序顺序)。
我还在使用类似函数的宏。理想情况下,我希望有<#macro rendertable filteredDatatypelist datatype>
在过去,我调用宏来基于当前数据类型呈现标题、页脚和行,但我试图摆脱这种做法,希望有一个单一的宏来呈现每个数据类型的子列表上的整个表格。
也就是说,将数据项列表发送给宏。所以,例如,在上述数据中,我会调用rendertable
宏3次,分别针对数据类型1、3和4。
我尝试创建使用filter
的子列表,但这似乎可能会导致性能问题,每个数据类型的时间复杂度为O(n)。即使如此,我也不确定它会如何正常工作。***还请注意,我不知道有多少数据类型或它们的值是什么。***我还查看了seq_index_of
和seq_last_index_of
,但同样我不知道不同的数据类型会是什么。***我考虑首先创建一个唯一数据类型的列表,但我也不知道如何做。***换句话说,我不知道如何做类似于
<#assign dataForDataType = dataList?filter(data.datatype = 1)>
<#list dataForDataType as x>$<@renderTable x 1></#list>
***除非在上述情况下,我硬编码数据类型,它仅适用于硬编码的一个数据类型。***即使它是O(n),我认为我可以接受,但问题是我不知道如何对数据类型列表执行此操作。如何实现这一点将不胜感激。
英文:
I'm looking for a way to generate a grouped by report using Freemarker based on the dataType (int) from a list of data items.
So for example I have:
data.datatype = 1 where data has id = 1
data.datatype = 1 where data has id = 4
data.datatype = 1 where data has id = 7
data.datatype = 3 where data has id = 2
data.datatype = 3 where data has id = 3
data.datatype = 4 where data has id = 5
... and so on
The sequence is sorted by datatype but at the same time I need to keep the data items in their respective order (secondary sort order).
I'm also using macros like functions. Ideally I'd love to have <#macro rendertable filteredDatatypelist datatype>
In the past I did called a macro to render the header, footer, and row based on the current datatype but I'm trying to move away from that and have a single macro to render the whole table on the sublist for each datatype.
That is to say send the macro a list of the data items for the datatype. So for example in the above data I would call the rendertable
macro 3 times, once for datatype 1, 3, and 4.
I looked at trying to create a sublist using filter
but this seemed like it could be a performance issue with O(n) for each datatype. Not ideal but even then I'm not sure how it would work exactly. Also please note that I have no idea how many datatypes there are or what their values could be. I also looked at seq_index_of
and seq_last_index_of
but again I don't know what the different datatypes will be. I considered creating a list of unique datatypes first but I have no idea how to do that either. In other words I'm not sure how to even do something like
<#assign dataForDataType = dataList?filter(data.datatype = 1)>
<#list dataForDataType as x>$<@renderTable x 1></#list>
Except that in the case above I'm hardcoding the datatype and it only works for one datatype that is hardcoded. Even if it's O(n) I think I would be ok with it but the issue is that I don't know how to do it for a list of datatypes. Any help on how this can be achieved would be greatly appreciated.
答案1
得分: 0
我最终做的是创建一个扩展接口 TemplateMethodModelEx
的类,该类接受数据列表并返回数据类型列表。然后,我通过循环遍历数据类型,使用另一个函数从另一个 TemplateMethodModelEx
中获取特定数据类型的数据项。示例代码如下:
<#assign datatypes = getDistinctDataTypes(dataList)/>
<#list datatypes as datatype>
数据类型: ${datatype.id}
<#list getDataForDatatype(dataList, datatype) as data>
${data.whatever}
</#list>
</#list>
然后,我创建了类似以下示例的类:
public class GetDistinctDataTypes implements TemplateMethodModelEx {
@Override
public Object exec(List arguments) throws TemplateModelException {
// 测试代码省略,假设一切都能正常工作
DefaultListAdapter defaultListAdapter = ((DefaultListAdapter)arguments.get(0));
List<Data> dataList = (List<Data>)defaultListAdapter.getWrappedObject();
// 进行必要的操作并返回数据类型列表
return getDistinctDataTypesListFromDataList(dataList);
}
}
然后,我将该方法添加到配置中,以便在模板中使用。你可以在FreeMarker文件中执行这一操作,但我认为在Java代码中更好。
CONFIGURATION.setSharedVariable("getDistinctDataTypes", new GetDistinctDataTypes());
有关更多关于 方法指令 的详细信息,请参阅FreeMarker文档页面。
英文:
What I ended up doing was creating a class that extended the interface TemplateMethodModelEx
that would take in the list of data and then return a list of datatypes. I then looped through the datatypes and then using another function got the list of data items for a specific datatypes through another TemplateMethodModelEx.
Something along the lines of:
<#assign datatypes = getDistinctDataTypes(dataList)/>
<#list datatypes as datatype>
Datatype: ${datatype.id}
<#list getDataForDatatype(dataList, datatype) as data>
${data.whatever}
</#list>
</#list>
Then I have classes such as this example:
public class GetDistinctDataTypes implements TemplateMethodModelEx {
@Override
public Object exec(List arguments) throws TemplateModelException
{
// Testing code is omitted for brevity and everything is assumed to just work and be correct.
DefaultListAdapter defaultListAdapter = ((DefaultListAdapter)arguments.get(0));
List<Data> dataList = (List<Data>)defaultListAdapter.getWrappedObject();
// Do what I need and return list of datatypes
return getDistinctDataTypesListFromDataList(dataList);
}
}
I then also added the method to the Configuration so that it can be used. You can do it in the freemarker file but I find it's better in the Java code.
CONFIGURATION.setSharedVariable("getDistinctDataTypes", new GetDistinctDataTypes());
You can find more details on the following Freemarker document page about method directives.
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论