www.digitalmars.com         C & C++   DMDScript  

digitalmars.D.learn - Manipulate slice or specific element of range and return range

reply Timoses <timosesu gmail.com> writes:
Hey,

I'm struggling to find a way to achieve this. I've looked through 
std.algorithm but didn't find anything.. Maybe I'm blind.

What I would like to do is filter out all spaces in a string and 
change the front letter to lower case:

     string m = "My Capital String";
     string lower = m
         .filter!(c => c != ' ')
         .<executeAt>!(0, c => c.toLower) // executeAt does not 
exist
         .array.to!string;
     assert(lower == "myCapitalString");

or sth like

     m.filter!(...)
         .map!((element, int index) {
             if (index == 0)
                 return element.toLower;
             else
                 break; // stop since we are done manipulating 
range
         });

Anyway to do this?
Mar 21 2018
next sibling parent reply Simen =?UTF-8?B?S2rDpnLDpXM=?= <simen.kjaras gmail.com> writes:
On Wednesday, 21 March 2018 at 11:30:28 UTC, Timoses wrote:
 Hey,

 I'm struggling to find a way to achieve this. I've looked 
 through std.algorithm but didn't find anything.. Maybe I'm 
 blind.

 What I would like to do is filter out all spaces in a string 
 and change the front letter to lower case:
https://xkcd.com/208/ unittest { assert("my capitalized string".capitalize == "myCapitalizedString"); } auto capitalize(string s) { import std.regex, std.uni; return s.replaceAll!(a => a[1].toUpper)(regex(" (.)")); } -- Simen
Mar 21 2018
parent Timoses <timosesu gmail.com> writes:
On Wednesday, 21 March 2018 at 12:07:49 UTC, Simen Kjærås wrote:
 On Wednesday, 21 March 2018 at 11:30:28 UTC, Timoses wrote:
 unittest {
     assert("my capitalized string".capitalize == 
 "myCapitalizedString");
 }

 auto capitalize(string s) {
     import std.regex, std.uni;

     return s.replaceAll!(a => a[1].toUpper)(regex(" (.)"));
 }
Ty! This definitely put me on the right track regarding strings.
Mar 21 2018
prev sibling next sibling parent reply =?UTF-8?Q?Ali_=c3=87ehreli?= <acehreli yahoo.com> writes:
On 03/21/2018 04:30 AM, Timoses wrote:
 Hey,
 
 I'm struggling to find a way to achieve this. I've looked through 
 std.algorithm but didn't find anything.. Maybe I'm blind.
 
 What I would like to do is filter out all spaces in a string and change 
 the front letter to lower case:
 
      string m = "My Capital String";
      string lower = m
          .filter!(c => c != ' ')
          .<executeAt>!(0, c => c.toLower) // executeAt does not exist
          .array.to!string;
      assert(lower == "myCapitalString");
 
 or sth like
 
      m.filter!(...)
          .map!((element, int index) {
              if (index == 0)
                  return element.toLower;
              else
                  break; // stop since we are done manipulating
range
          });
 
 Anyway to do this?
Here is another one that uses ForwardRange. import std.range; // empty, take, save, chain, popFrontN; import std.uni; // asLowerCase; import std.algorithm; // equal, filter; import std.conv; // text; auto initialLowerCased(R)(R str, size_t N = 1) { if (str.empty) { N = 0; } auto frontPart = str.take(N); auto rest = str.save; rest.popFrontN(N); return chain(frontPart.asLowerCase, rest); } unittest { assert(initialLowerCased("My Test String", 4).equal("my test String")); assert(initialLowerCased("").equal("")); } auto foo(R)(R str) { return str.filter!(c => c != ' ').initialLowerCased; } void main() { auto result = foo("My Capital String"); // result above is a range. std.conv.text can make a string: string lower = result.text; assert(lower == "myCapitalString"); } Ali
Mar 21 2018
parent Timoses <timosesu gmail.com> writes:
On Wednesday, 21 March 2018 at 12:53:56 UTC, Ali Çehreli wrote:
 Here is another one that uses ForwardRange.

 import std.range; // empty, take, save, chain, popFrontN;
 import std.uni; // asLowerCase;
 import std.algorithm; // equal, filter;
 import std.conv; // text;

 auto initialLowerCased(R)(R str, size_t N = 1) {
     if (str.empty) {
         N = 0;
     }
     auto frontPart = str.take(N);
     auto rest = str.save;
     rest.popFrontN(N);

     return chain(frontPart.asLowerCase, rest);
 }

 unittest {
     assert(initialLowerCased("My Test String", 4).equal("my 
 test String"));
     assert(initialLowerCased("").equal(""));
 }

 auto foo(R)(R str) {
     return str.filter!(c => c != ' ').initialLowerCased;
 }

 void main() {
     auto result = foo("My Capital String");
     // result above is a range. std.conv.text can make a string:
     string lower = result.text;
     assert(lower == "myCapitalString");
 }

 Ali
I like it! I remember having a similar situation another time where it was not about strings. I wonder why there is no method for this in the standard library that can execute a predicate on specific elements of a range..
Mar 21 2018
prev sibling parent reply Seb <seb wilzba.ch> writes:
On Wednesday, 21 March 2018 at 11:30:28 UTC, Timoses wrote:
 Hey,

 I'm struggling to find a way to achieve this. I've looked 
 through std.algorithm but didn't find anything.. Maybe I'm 
 blind.

 What I would like to do is filter out all spaces in a string 
 and change the front letter to lower case:

     string m = "My Capital String";
     string lower = m
         .filter!(c => c != ' ')
         .<executeAt>!(0, c => c.toLower) // executeAt does not 
 exist
         .array.to!string;
     assert(lower == "myCapitalString");

 or sth like

     m.filter!(...)
         .map!((element, int index) {
             if (index == 0)
                 return element.toLower;
             else
                 break; // stop since we are done manipulating 
 range
         });

 Anyway to do this?
No need for regular expressions. D is powerful enough without them: ``` alias lowercased = (m, n) => m.take(n).asLowerCase.chain(m.drop(n)); ``` https://run.dlang.io/is/cSL0si
Mar 21 2018
parent reply David Bennett <davidbennett bravevision.com> writes:
On Thursday, 22 March 2018 at 04:49:39 UTC, Seb wrote:
 No need for regular expressions. D is powerful enough without 
 them:

 ```
 alias lowercased = (m, n) => 
 m.take(n).asLowerCase.chain(m.drop(n));
 ```

 https://run.dlang.io/is/cSL0si
And with the filter, so it passes the assert: ``` string input = "My Capital String"; auto lower1 = input.take(1).asLowerCase.chain(input.drop(1).filter!(c => c != ' ')).array; assert(lower1 == "myCapitalString"); ``` Also a few more options (including a slice version): https://run.dlang.io/is/dZHcSo As the input is never read until the array() is run, each element in the array should only be copied from RAM to the stack once. And if you compile with LDC a lot of it can be inlined and the stack copies of the range structs and elements should be minimised even further.
Mar 22 2018
parent Timoses <timosesu gmail.com> writes:
On Thursday, 22 March 2018 at 07:34:18 UTC, David Bennett wrote:
 On Thursday, 22 March 2018 at 04:49:39 UTC, Seb wrote:
 ```
 alias lowercased = (m, n) => 
 m.take(n).asLowerCase.chain(m.drop(n));
 ```
``` string input = "My Capital String"; auto lower1 = input.take(1).asLowerCase.chain(input.drop(1).filter!(c => c != ' ')).array; assert(lower1 == "myCapitalString"); ``` Also a few more options (including a slice version): https://run.dlang.io/is/dZHcSo As the input is never read until the array() is run, each element in the array should only be copied from RAM to the stack once. And if you compile with LDC a lot of it can be inlined and the stack copies of the range structs and elements should be minimised even further.
Very inspiring snippets!
Mar 28 2018