英文:
Collapse data structure
问题
{
"attributes": {
"name": "\"physics\""
},
"elements": {
"material": [
{
"attributes": {
"name": "\"blue\""
},
"elements": {
"color": [
{
"attributes": {
"rgba": [
-1.2,
0,
0.8,
1
]
}
}
]
}
},
{
"attributes": {
"name": "\"black\""
},
"elements": {
"color": [
{
"attributes": {
"rgba": [
0,
0,
0,
1
]
}
}
]
}
}
]
}
}
在Rascal中,您可以使用类似JavaScript中的方法将attributes
和elements
嵌套为对象。以下是相应的Rascal代码:
data JsonValue = object attributes: map[str, JsonValue] elements: map[str, list[JsonValue]];
JsonValue collapse(JsonValue e) {
map[str, JsonValue] elements = ();
for (key <- dom(e.elements)) {
elements[key] = collapse(e.elements[key]);
}
return e.attributes + elements;
}
上述Rascal代码将attributes
和elements
嵌套为一个JsonValue
对象。
英文:
I want to remove the inner keywords attributes and elements such that the attributes and elements are part of the json object itself. Is there a way in doing this in Rascal for a json file.
{
"attributes": {
"name": "\"physics\""
},
"elements": {
"material": [
{
"attributes": {
"name": "\"blue\""
},
"elements": {
"color": [
{
"attributes": {
"rgba": [
-1.2,
0,
0.8,
1
]
}
}
]
}
},
{
"attributes": {
"name": "\"black\""
},
"elements": {
"color": [
{
"attributes": {
"rgba": [
0,
0,
0,
1
]
}
}
]
}
}
],
}
}
I created a data structure that parses key value pairs of a xml file. In the json file I want to get rid of the attributes and elements and use nested objects instead of elements.
In javascript I got this to work.
function collapse(e){
let elements = {};
for(const key in e.elements){
for(const element of e.elements[key]){
elements[key] = collapse(element)
}
}
return {...e.attributes, ...elements}
}
答案1
得分: 0
这个答案是一个非常具体的转换,仅适用于您特定选择的JSON对象,这些对象每个都有"attributes"和"elements"字段。首先,我们可以不明白为什么需要对对象进行"双重编码",但无论如何,您可以使用Rascal来移除它。
这是一个自底向上的转换,它匹配每个节点的结构,并使用标准库中的Node
模块中的函数将其转换为另一个节点。我们需要这个来创建任意阶数的节点,对于这种情况,尚无语法。
import Map;
import Node;
// 重要的工作是模式匹配,它使用编码的协议:两个名为"attributes"和"elements"的属性,每个属性指向另一个编码为映射的对象。
value transform("object"(attributes=node attrs, elements=node elems))
= makeNode([transform(x) | value x <- getKeywordParameters(elems)<1>],
keywordParameters=(k:transform(b) | <k,v> <- toRel(getKeywordParameters(attrs));
// 列表需要一些递归
value transform(list[value] l) = [transform(e) | e <- l];
// 所有其他内容都是一对一复制
default value transform(value v) = v;
我还没有进行测试,但您可以获得一个大致的想法。递归加上基于模式的分派用于每种情况。
英文:
This answer is a very specific transformation that is only relevant for your particular choice of JSON objects which have "attributes" and "elements" fields for every object. It is a bit puzzling why we have this "double encoding" of objects in the first place, but nevertheless you can remove it with Rascal.
This is a bottom-up transformation that matches the structure of every node and transforms it to another using functions from the Node
module in the standard library. We need this to be able to create nodes of arbitrary arities, for which there is no syntax yet.
import Map;
import Node;
// the heavy work is the pattern match that uses the contract of the
// encoding: two attributes named "attributes" and "elements", each pointing to another object that encodes a map.
value transform("object"(attributes=node attrs, elements=node elems))
= makeNode([transform(x) | value x <- getKeywordParameters(elems)<1>],
keywordParameters=(k:transform(b) | <k,v> <- toRel(getKeywordParameters(attrs));
// lists need some recursion
value transform(list[value] l) = [transform(e) | e <- l];
// all other stuff is copied one-to-one
default value transform(value v) = v;
I did not test this yet, but you get a general idea. Recursion + pattern based dispatch for each case.
答案2
得分: 0
以下是代码的中文翻译:
我在Rascal中使用以下函数使其工作:
map[str, value] urdfToMap(URDF urdf, map[str, value] result = ()) {
for (a <- urdf.attributes) {
URDFValue val = urdf.attributes[a];
if (string(s) := val) {
result += (a: s);
} else if (number(n) := val) {
result += (a: n);
} else {
result += (a: val);
}
}
for (e <- urdf.elements) {
list[URDF] elements = urdf.elements[e];
list[map[str, value]] tmp = [];
for (element <- urdf.elements[e]) {
if (size(elements) <= 1) {
result += (e: urdfToMap(element));
} else {
tmp += [urdfToMap(element)];
}
}
if (e notin result) {
result += (e: tmp);
}
}
return result;
}
希望这对你有帮助。
英文:
I got it working in Rascal using this function:
map[str,value] urdfToMap(URDF urdf,map[str,value] result = ()){
for(a <- urdf.attributes){
URDFValue val = urdf.attributes[a];
if(string(s) := val){
result += (a:s);
}else if(number(n) := val){
result += (a:n);
}else{
result += (a:val);
}
}
for(e <- urdf.elements){
list[URDF] elements = urdf.elements[e];
list[map[str,value]] tmp = [];
for(element <- urdf.elements[e]){
if(size(elements) <= 1){
result += (e:urdfToMap(element));
}else{
tmp += [urdfToMap(element)];
}
}
if(e notin result){
result += (e:tmp);
}
}
return result;}
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论