我有一个列表,其中包含多级嵌套列表。每个列表都可以包含字符串和其他类型实例。
E.g。
var list = [ 'a', 'w', ['e', ['f', new Object(), 'f'], 'g'], 't', 'e'];
我想编写一个函数(比如compress
)来将字符串与其兄弟节点组合在一起,并保持其他类型实例不变,最后得到一个没有嵌套列表的列表。
compress(list){ // 如何 ? }
compress(list)
的结果将是:
['awef', new Object(), 'fgte']
它是否是快速而明确的解决方案?
答案 0 :(得分:5)
Terse和功能性FTW
List compress(Iterable iterable) => concat(flatten(iterable));
Iterable flatten(Iterable iterable) =>
iterable.expand((e) => e is Iterable ? flatten(e) : [e]);
List concat(Iterable iterable) => iterable.fold([], (list, e) =>
list..add((e is String && list.isNotEmpty && list.last is String)
? list.removeLast() + e : e));
答案 1 :(得分:2)
这包括两个问题,一个非常标准的问题(展平列表),然后充分加入字符串。
flatten(Iterable l) => l.fold([], (List list, element) {
if (element is Iterable)
list.addAll(flatten(element));
else
list.add(element);
return list;
});
concat(Iterable l) => l.fold([], (List list, element) {
if (element is String && !list.isEmpty && list.last is String)
list.add(list.removeLast() + element);
else
list.add(element);
return list;
});
void main() {
var nested = [ 'a', 'w', ['e', ['f', new Object(), 'f'], 'g'], 't', 'e'];
print(concat(flatten(nested));
}
更新
一种变形的concat
,灵感来自Greg Lowe(完全像我的“大”和他的那个,但更加浓缩):
concat(Iterable list) => list.fold([], (List xs, x) => xs..add(
x is String && !xs.isEmpty && xs.last is String ? xs.removeLast() + x : x));
你可以根据需要结合他和我的功能,他们做的完全相同。
答案 2 :(得分:2)
如果您有很多字符串,可能需要使用StringBuffer进行连接。 我的猜测是,在大多数情况下,这不是问题。
List compress(List list) {
var sb = new StringBuffer();
List result = [];
List compressRec(List list) {
for (var element in list) {
if (element is String) {
sb.write(element);
} else if (element is List) {
compressRec(list);
} else {
if (sb.isNotEmpty()) {
result.add(sb.toString());
sb.clear();
}
result.add(element);
}
}
}
compressRec(list)
if (sb.isNotEmpty()) {
result.add(sb.toString());
}
return result;
}
答案 3 :(得分:1)
这是我的猜测:
compress(List l, [List p]) => l.fold(p != null ? p : [], (List t, e) {
if (e is String) {
if (t.isEmpty || t.last is! String) t.add(e);
else t.add(t.removeLast() + e);
} else if (e is List) compress(e, t);
else t.add(e);
return t;
});
答案 4 :(得分:0)
我的尝试
List flatten(List l) {
List result = [''];
int cur = 0;
var add = (f) {
if(f is String) {
result[cur] += f;
} else {
result.add(f);
result.add('');
cur += 2;
}
};
l.forEach((e) {
if(e is List) {
flatten(e).forEach((e) => add(e));
} else {
add(e);
}
});
return result;
}