一個老題目,將下面古詩文由橫排,變成古文豎排模式:
靜夜思 李白
床前明月光,
疑似地上霜。
舉頭望明月,
低頭思故鄉。
變成:
低|舉|疑|床|靜
頭|頭|似|前|夜
思|望|地|明|思
故|明|上|月|
鄉|月|霜|光|李
。|,|。|,|白
1.原始文本轉成二維數組,簡化起見,暫時去掉標點符號和標題作者:
console.log("床前明月光\n疑似地上霜\n舉頭望明月\n低頭思故鄉".split(/\n/).map( v => v.split(''))
);
輸出:
[[ '床', '前', '明', '月', '光' ],[ '疑', '似', '地', '上', '霜' ],[ '舉', '頭', '望', '明', '月' ],[ '低', '頭', '思', '故', '鄉' ]
]
直接一行行輸出的時候,就是橫排輸出,變成豎排,剛好是行列互換,在二維數組、矩陣中,就是矩陣轉置transpose,4x5的矩陣行列互換后,變成5x4,現在要實現一個transpose函數:
let arr = [[1, 2, 3],[4, 5, 6]
];
// 取首行,循環每一列,循環列的時候,取對應列的元素變成行返回,如果某行元素不足首行,可以填充空白字符
console.log( arr[0].map((_, col) =>arr.map(row => row[col]))
);
轉換后變成:
[ [ 1, 4 ], [ 2, 5 ], [ 3, 6 ] ]
封裝成一個函數:
// tranpose函數實現有很多種,這是最簡單一種
let transpose = arr => {return arr[0].map((_, col) =>arr.map(row => row[col]));
};
console.log( transpose("床前明月光\n疑似地上霜\n舉頭望明月\n低頭思故鄉".split(/\n/).map( v => v.split('')))
);
輸出:
[[ '床', '疑', '舉', '低' ],[ '前', '似', '頭', '頭' ],[ '明', '地', '望', '思' ],[ '月', '上', '明', '故' ],[ '光', '霜', '月', '鄉' ]
]
變成字符串輸出:
let transpose = arr => {return arr[0].map((_, col) =>arr.map(row => row[col]));
};
console.log( transpose("床前明月光\n疑似地上霜\n舉頭望明月\n低頭思故鄉".split(/\n/).map( v => v.split(''))).map( row => row.join("|") ).join("\n")
);
輸出:
床|疑|舉|低
前|似|頭|頭
明|地|望|思
月|上|明|故
光|霜|月|鄉
現在是從左到右,要變成從右向左,每一行還需要先反轉數組:row.reverse()
let transpose = arr => {return arr[0].map((_, col) =>arr.map(row => row[col]));
};
let str = transpose("床前明月光\n疑似地上霜\n舉頭望明月\n低頭思故鄉".split(/\n/).map( v => v.split('')))
.map( row => row.reverse().join("|") )
.join("\n");
console.log(str);
輸出:
低|舉|疑|床
頭|頭|似|前
思|望|地|明
故|明|上|月
鄉|月|霜|光
如果不想定義函數,可以用reduce來實現:
console.log([[1, 2, 3],[4, 5, 6]].reduce((s, a) => (a.map((v, j)=> s[j] = (s[j] || []).concat([v])), s), [])
);
輸出:
[ [ 1, 4 ], [ 2, 5 ], [ 3, 6 ] ]
reduce改寫:
let str = '靜夜思 李白\n床前明月光,\n疑似地上霜。\n舉頭望明月,\n低頭思故鄉。'.split(/\n/)
.map( v => v.split('') )
.reduce((s, a) => (a.map((v, j)=> s[j] = (s[j] || []).concat([v])), s), [])
.map( d => d.reverse().join('|') )
.join('\n');
console.log(str);
輸出:
低|舉|疑|床|靜
頭|頭|似|前|夜
思|望|地|明|思
故|明|上|月|
鄉|月|霜|光|李
。|,|。|,|白
ruby內置了transpose函數:
# puts "靜夜思 李白\n床前明月光,\n疑似地上霜。\n舉頭望明月,\n低頭思故鄉。".split(/\n/).map(&:chars).transpose.map{ it.reverse * '|' } * "\n"
# csdn的 ruby 版本過低,上面代碼不能正常運行
puts "靜夜思 李白\n床前明月光,\n疑似地上霜。\n舉頭望明月,\n低頭思故鄉。".split(/\n/).map(&:chars).transpose.map{|it| it.reverse.join('|') }.join("\n")
輸出:
低|舉|疑|床|靜
頭|頭|似|前|夜
思|望|地|明|思
故|明|上|月|
鄉|月|霜|光|李
。|,|。|,|白
完。