我的代码在控制台中有一个输出,如下面的示例所示,
... columns=20xs, viewport_supported=true, wta=false, ..., mmf=false
... columns=11xs, viewport_supported=false, wta=false, ..., mmf=true
... columns=15xs, viewport_supported=true, wta=false, ..., mmf=false
我想通过将常用字符串提取到'='符号并将其作为列标题及其值放在其列中来重新排列它。如何在Java中开始这样做?
我正在寻找如下输出:
columns viewport_supported wta and so on
20xs true false
11xs false false
15xs true false
答案 0 :(得分:1)
查看split
类的String
方法。您可能希望使用它将每行拆分为单独的column=value
部分,然后再次从列中拆分列。这应该让你开始 - 再次问你是否卡住了。
答案 1 :(得分:1)
好的,到此为止。这是使用Guava
的解决方案首先,这是一个名为Table
的辅助类(不要与Guava的Table
接口混淆):
public class Table {
private static final MapSplitter MAP_SPLITTER =
Splitter.on(',').trimResults().withKeyValueSeparator(Splitter.on('='));
private final Multimap<String, String> values =
Multimaps.newListMultimap(
// keys are sorted, values maintain insertion order
Maps.<String, Collection<String>>newTreeMap(),
new Supplier<List<String>>() {
@Override public List<String> get() {
return Lists.newArrayList();
}
});
// keys are sorted, to correspond with the order of the other map
private final Map<String, Integer> lengths = Maps.newTreeMap();
private int modCount = 0;
public void addRow(final String row) {
modCount++;
final Map<String, String> lineData = MAP_SPLITTER.split(row);
final boolean empty = values.isEmpty();
if (!empty && values.keySet().size() != lineData.size()) {
throw new IllegalArgumentException("Bad row: " + row);
}
for (final Entry<String, String> entry : lineData.entrySet()) {
final String key = entry.getKey();
final String value = entry.getValue();
if (!empty && !values.containsKey(key)) {
throw new IllegalArgumentException(
"Bad column: " + key + " in row " + row);
}
final Integer tempLength;
if (empty) {
tempLength = key.length();
} else {
tempLength = lengths.get(key);
}
values.put(key, value);
lengths.put(key, Math.max(value.length(), tempLength));
}
}
public Iterable<String> getHeaders() {
return Collections.unmodifiableSet(values.asMap().keySet());
}
public Iterable<Integer> getColumnSizes() {
return Collections.unmodifiableCollection(lengths.values());
}
public Iterable<Iterable<String>> getData() {
return new Iterable<Iterable<String>>() {
@Override
public Iterator<Iterable<String>> iterator() {
return new RowIterator();
}
};
}
private class RowIterator extends AbstractIterator<Iterable<String>> {
private int rowIndex = -1;
private final int modCount = Table.this.modCount;
private final int maxRow =
values.asMap().values().iterator().next().size() - 1;
@Override
protected Iterable<String> computeNext() {
if (Table.this.modCount != modCount) {
throw new ConcurrentModificationException();
}
final Map<String, Collection<String>> map = values.asMap();
if (rowIndex++ == maxRow) {
return endOfData();
}
final List<String> data =
Lists.newArrayListWithCapacity(map.size());
for (final Collection<String> column : map.values()) {
data.add(((List<String>) column).get(rowIndex));
}
return Collections.unmodifiableCollection(data);
}
}
}
现在我们可以使用此表类来格式化您的数据:
final String input = "columns=20xs, viewport_supported=true, wta=false, mmf=false\n"
+ "columns=11xs, viewport_supported=false, wta=false, mmf=true \n"
+ "columns=15xs, viewport_supported=true, wta=false, mmf=false";
final Table table = new Table();
final Iterable<String> lines = Splitter.on('\n').trimResults().split(input);
for (final String line : lines) {
// add one row of data
table.addRow(line);
}
// Using Appendable so you can easily switch to some other implementation,
// e.g. System.out
final Appendable appendable = new StringBuilder();
final Iterable<Integer> columnSizes = table.getColumnSizes();
final Iterable<String> headers = table.getHeaders();
final Iterator<String> headerIterator = headers.iterator();
final Iterable<Iterable<String>> data = table.getData();
{
// write headers
boolean first = true;
for (final Integer size : columnSizes) {
if (first) {
first = false;
} else {
appendable.append(" | ");
}
appendable.append(Strings.padEnd(headerIterator.next(), size, ' '));
}
appendable.append('\n');
}
{
// underline headers
boolean first = true;
for (final Integer size : columnSizes) {
if (first) {
first = false;
} else {
appendable.append("-+-");
}
appendable.append(Strings.repeat("-", size));
}
appendable.append('\n');
}
// write data
for (final Iterable<String> row : data) {
boolean first = true;
final Iterator<String> rowIterator = row.iterator();
for (final Integer size : columnSizes) {
if (first) {
first = false;
} else {
appendable.append(" | ");
}
appendable.append(Strings.padEnd(rowIterator.next(), size, ' '));
}
appendable.append('\n');
}
System.out.println(appendable);
这是输出:
columns | mmf | viewport_supported | wta
--------+-------+--------------------+------
20xs | false | true | false
11xs | true | false | false
15xs | false | true | false
如果您的行具有可变内容(并非所有行都包含相同的列),这将更加困难,这就是我强制所有行必须包含相同列的原因。随意改变(或其他任何东西)。
答案 2 :(得分:0)
我最近完成了你想做的事情。
我不确定您的数据是如何存储的,但出于演示目的,我使用字符串'a'。 让我们说字符串'a'包含:
String a = 20xs, true, false;
然后,您可以使用split()
函数来分割句子String并将它们分成单词String。以下代码执行此操作:
a = a.trim();
String[] words = a.split(","); // creates array of Strings with each words in String a
// words would contain [20xs] [true] [false]
我写了一个函数,它会在每个单词的后面填充空格。
/** Add spaces to Strings so that all of the are of same number of characters
* @param str String to be padded
* @param n total number words String should be padded to
* @return str Padded string
*/
private String padString(String str, int n){
if(str.length() < n){
for(int j = str.length(); j < n; j++){
str += " ";
} // end for
} // end if
return str;
} // end padString
所以现在让我们说:如果你这样做:
System.out.println(padString(words[0],15) + padString(words[1],15) + padString(words[2],15)
// So the result will be [20xs ] [true ] [false ]
当您编写上述代码时,您将在控制台中获得以下内容:
20xs true false
如果你需要更大的差距,你可以在padString()
函数中传递更高的值
正如我所看到的那样,列标题始终是相同的,您可以首先使用相同数量的填充来编写println代码,因此它始终从头开始,就像标题一样。
我希望这会有所帮助。
答案 3 :(得分:0)
我终于能够这样做:使用split()方法拆分字符串,创建一个Map动态数组,并在'equals to sign'两侧分别为字符串分配键和值。然后通过解析表示第一个数据行的映射来打印标题信息,然后通过迭代Map中的对象来打印所有数据行。我的代码摘录如下。
/* delimiter */
String delimiter = ", ";
//给定的字符串将被提供的参数分隔符拆分。
String[] temp = capabilities.split(delimiter);
/* print substrings */
Map<String, String> row = new HashMap<String, String>();
for (int i = 0; i < temp.length; i++) {
String delimiter1 = "=";
String[] temp1 = null;
temp1 = temp[i].split(delimiter1);
if (temp1 != null && temp1.length == 2) {
row.put(temp1[0], temp1[1]);
}
}
dataRows.add(row);
// print the header --- but first, get the header information by parsing the map representing the first data row
List<String> fieldNames = new ArrayList<String>();
Map<String, String> firstRow = dataRows.get(0);
for (String fieldName : firstRow.keySet()) {
fieldNames.add(fieldName);
}
for (String fieldName : fieldNames) {
System.out.print("\t" + fieldName);
}
// now, print all data rows
for (Map<String, String> dataRow : dataRows) {
System.out.println("\n");
for (String fieldName : fieldNames) {
System.out.print("\t" + dataRow.get(fieldName));}
谢谢大家的帮助。