{"id":102844,"date":"2019-09-09T07:00:00","date_gmt":"2019-09-09T14:00:00","guid":{"rendered":"http:\/\/devblogs.microsoft.com\/oldnewthing\/?p=102844"},"modified":"2019-09-08T21:51:09","modified_gmt":"2019-09-09T04:51:09","slug":"20190909-00","status":"publish","type":"post","link":"https:\/\/devblogs.microsoft.com\/oldnewthing\/20190909-00\/?p=102844","title":{"rendered":"PowerShell programming puzzle: Convert snake_case to PascalCase in one line"},"content":{"rendered":"<p>A friend posed this PowerShell programming puzzle (P\u00b3), which represents an actual problem he had to solve:<\/p>\n<blockquote class=\"q\"><p>Given a string in <code>$t<\/code> in <tt>snake_case<\/tt> or <tt>SHOUTY_SNAKE_CASE<\/tt>, return the corresponding PascalCase string. You may assume no consecutive underscores.<\/p><\/blockquote>\n<p>The initial version went like this:<\/p>\n<pre>$uc = $true; \r\n[string]::Concat(($t.ToCharArray() | % { \r\n  if ($uc) { ($_ -as [string]).ToUpper(); $uc = $false; } \r\n  elseif ($_ -eq '_') { $uc = $true; } \r\n  else { ($_ -as [string]).ToLower();} \r\n}))\r\n<\/pre>\n<p>This is a straightforward translation of the requirements: Walk through the string one character at a time. Capitalize the first letter and any letter that follows an underscore. Everything else becomes lowercase.<\/p>\n<p>I countered with this crazy one-liner:<\/p>\n<pre style=\"white-space: pre-wrap;\">(Get-Culture).TextInfo.ToTitleCase(($t.ToLower() -replace \"_\", \" \")) -replace \" \", \"\"\r\n<\/pre>\n<p>This version cheats like crazy, but hey, we&#8217;re code-golfing. It relies on the capitalization rules of the English language, and it assumes that every word starts with a letter.<\/p>\n<p>The idea is to take advantage of <code>To\u00adTitle\u00adCase<\/code>, which capitalizes the first letter of each space-separated word. All we have to do is transform the string into something that we can feed into <code>To\u00adTitle\u00adCase<\/code>.<\/p>\n<p>So start with the string, convert it entirely to lowercase (to avoid the feature of <code>To\u00adTitle\u00adCase<\/code> that preserves all-capitalized words), and change the underscores to spaces. Now we can ask <code>To\u00adTitle\u00adCase<\/code> to capitalize the first letter of each word. Then we compress out the spaces with a final <code>-replace<\/code>.<\/p>\n<p>A less crazy version would be something like this:<\/p>\n<pre style=\"white-space: pre-wrap;\">[regex]::replace($t.ToLower(), '(^|_)(.)', { $args[0].Groups[2].Value.ToUpper()})\r\n<\/pre>\n<p>First, we convert the entire string to lowercase. Then we search for each character that comes after an underscore (considering the first character of the string to be after an imaginary leading underscore) and capitalize it. The underscore itself is not returned, which causes it to vanish.<\/p>\n<p>&nbsp;<\/p>\n","protected":false},"excerpt":{"rendered":"<p>Abusing linguistic helper functions for fun.<\/p>\n","protected":false},"author":1069,"featured_media":111744,"comment_status":"open","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"_acf_changed":false,"footnotes":""},"categories":[1],"tags":[25],"class_list":["post-102844","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-oldnewthing","tag-code"],"acf":[],"blog_post_summary":"<p>Abusing linguistic helper functions for fun.<\/p>\n","_links":{"self":[{"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/posts\/102844","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/users\/1069"}],"replies":[{"embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/comments?post=102844"}],"version-history":[{"count":0,"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/posts\/102844\/revisions"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/media\/111744"}],"wp:attachment":[{"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/media?parent=102844"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/categories?post=102844"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/tags?post=102844"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}