以下の内容はhttps://tech.guitarrapc.com/entry/2013/02/05/150238より取得しました。


PowerShellでStringをChar[]に変換する

表題の事案には、シェル芸で試みている時に巡り会っていたのです。 さてちょうど、いつもの問題出題サイトで表題の試みがありました。

Convert a string to a character array

たまたま経験則で答えが出てたのですが、改めて勉強になりました。 さっそく見てみます。

お題目

"PowerShell"というStringを、一文字ずつのChar[]に変換しなさい。

つまり、こうなるはずです。

P
o
w
e
r
S
h
e
l
l

縛り

  • [char[]]へのキャストは禁止
  • String型が持つ.ToCharArrayメソッドは禁止

ソースにすると、これが禁止です。

[char[]]"PowerShell" #禁止
("PowerShell").ToCharArray() #禁止

型を調べてみましょう。

([char[]]"PowerShell").gettype().FullName
("PowerShell").ToCharArray().gettype().FullName

結果はChar[]型ですね。

System.Char[]
System.Char[]

コード例

一文字ずつ取り出す方法は、いくつか考えられます。

  • .GetEnumetrator()を利用
  • .GetEnumetrator()を利用して順次配列にいれていく
  • 配列(Array)にして一字ずつ取り出す
  • 正規表現して、結果をSplitメソッドへ
  • Splitメソッドを使う

それぞれを見ていきます。

.GetEnumetrator()を利用

まずはソースから。

$Enumerator="PowerShell".GetEnumerator()

実行してみましょう。

"------Enumerator"
$Enumerator.length
$Enumerator.GetType().Name
"------Enumerator"
$Enumerator
"------Enumerator"

結果です。

GetEnumerator()では型がCharEnumeratorになっていることが分かります。あと、順次Enumeratorしてるので…結果が変数には何も出力されていません。

------Enumerator
1
1
1
1
1
1
1
1
1
1
CharEnumerator
------Enumerator
------Enumerator

これは正常な動きです。

仮に出力したいならば変数に入れず実行すればいいわけです。つまりこうですね。

"PowerShell".GetEnumerator()

期待通り出力します。

P
o
w
e
r
S
h
e
l
l

.GetEnumetrator()を利用して順次配列にいれていく

ソースです。

$EnumeratorArray=@()
$EnumeratorArray += "PowerShell".GetEnumerator()

実行してみましょう。

"------EnumeratorArray"
$EnumeratorArray.length
$EnumeratorArray.GetType().Name
"------EnumeratorArray"
$EnumeratorArray
"------EnumeratorArray"

結果です。Char[]ではありませんが、配列に入れているのでObject[]になっていますね。

これならまぁ何とかです。変数にも格納できています。

------EnumeratorArray
10
Object[]
------EnumeratorArray
P
o
w
e
r
S
h
e
l
l
------EnumeratorArray

配列(Array)にして一字ずつ取り出す

インデックスを直接書かない理由は、他の文字でも流用するためです。毎度文字の度に変えるのはナンセンスです。

$Array=($z="Powershell")[0..$z.Length]

実行してみましょう。

"------Array"
$Array.length
$Array.GetType().Name
"------Array"
$Array
"------Array"

結果です。object[]型ですが一応上手くいきますね。

------Array
10
Object[]
------Array
P
o
w
e
r
s
h
e
l
l
------Array

正規表現して、結果をSplitメソッドへ

ソースです。

$regexsplit=[regex]::split("PowerShell","")

実行してみましょう。

"------regexsplit"
$regexsplit.length
$regexsplit.GetType().Name
"------regexsplit"
$regexsplit
"------regexsplit"

結果です。突込みどころが多いしアウトです。

まず、Splitメソッドで分割すると、結果はstring型になります。

加えて前後に余計な空白文字が1文字ずつ入って12文字になっています。

------regexsplit
12
String[]
------regexsplit

P
o
w
e
r
S
h
e
l
l

------regexsplit

Splitメソッドを使う

ソースです。

$split='PowerShell'-split'\B'

実行してみましょう。

"------split"
$split.length
$split.GetType().Name
"------split"
$split
"------split"

結果です。

先ほど同様の突込みでアウトです。当然、Splitメソッドで分割すると結果はstring型になります。

前後の余白が入らないだけマシですが。

------split
10
String[]
------split
P
o
w
e
r
S
h
e
l
l
------split

まとめ

配列に.GetEnumerator()でいれるか、$x[インデックス指定]を入れることでobject[]型は取得できます。Splitはstringになりますので注意です。

ありがたいことに、公開して10分で、某星人から指摘がありました。

だるじろうさん (@takeshik)

今回の例でいうとソースはこうです。

$linq =[System.Linq.Enumerable]::ToArray("PowerShell")

実行してみます。

"------linq"
$linq.length
$linq.GetType().FullName
"------linq"
$linq
"------linq"

結果です。

------linq
10
System.Char[]
------linq
P
o
w
e
r
S
h
e
l
l
------linq

おまけ

lからPまで、逆さに取得したい場合は?簡単な方法は配列のインデックスを逆にたどる方法です。

ソースはこうです。

($zz="Powershell")[-1..-($zz.Length)]

結果です。

l
l
e
h
s
r
e
w
o
P

これも星人はLinqでいくのが決まりということなのは最もでした。

だるじろうさん (@takeshik)

ソースはこうです。

[System.Linq.Enumerable]::Reverse('PowerShell')

結果です。

l
l
e
h
s
r
e
w
o
P

トドメの一言でした。真理です。

だるじろうさん (@takeshik)




以上の内容はhttps://tech.guitarrapc.com/entry/2013/02/05/150238より取得しました。
このページはhttp://font.textar.tv/のウェブフォントを使用してます

不具合報告/要望等はこちらへお願いします。
モバイルやる夫Viewer Ver0.14