Title case a sentence, forEach and slice vs substring

I solved it with mapping preety fast, but was stuck trying to build solution with forEach() method.

I ended up with little improvised task for myself. I think now I have the idea how to mutate array with forEach(). But I saw so many snippets in the last hour… not sure I ended up with good enough solution.

Also I used substring() here, but apparently slice() gets the job done. My suspicion: there is no much difference between these two in this case. But maybe there is?

SideNote. So far this section of curriculum is the coolest, having good time today)

Solution for step commented out, my own little snippet at the lower part of code.

/* Working solution with map()

function titleCase(str) {
  let arr = str.split(' ');  
  
  return arr.map(item => 
  (item[0].toUpperCase() + item.substring(1).toLowerCase())
  ).join(' ');

}

titleCase("I'm a little tea pot");
*/

//-----------------------

//additional improvised TASK for practice
//Capitalize arrStr, so every element will start with capital letter
//Mutate array not create new one
//Use forEach() method

let arrStr = ['qwe', 'rty', 'uio'];

arrStr.forEach((element, index, arrStr) => {
  arrStr[index] = element[0].toUpperCase() + element.substring(1);
  
})

console.log(arrStr);//[ 'Qwe', 'Rty', 'Uio' ]

I would say that editing the array as you loop over it with forEach feels hacky. I know you’re just playing around, but doing unexpected or hacky things makes for hard-to-understand code.

The difference between slice and substring are explained in their MDN pages, if I remember correctly. Something about how they handle out of bound indexes.

3 Likes

Yep, I’ve just felt like not having good enough grasp on forEach, so ‘to play around’ seemed like a good idea.
Couple of days ago you gave me some task about indexOf, so I’m trying to solve some improvised mini-problems from time to time. It feels like it’s useful approach to learning new tools.

My opinion, the only time to use forEach is for causing side effects with each item in the array, ie calling another function without caring about its return value.

// just log everything
list.forEach((item) => console.log(item));
// in a test runner like jest
// make a separate test for multiple test cases
testCases.forEach((testCase) => {
  it(`adds two numbers together correctly, ${testCase.a} + ${testCase.b}`, () => {
    expect(add(testCase.a, testCase.b)).toEqual(testCase.expected);
  });
});

Still, in most cases I’d prefer for…of cause then you’d have access to await, break, and continue.

2 Likes

Here’s the link to that explanation on MDN:

1 Like

I get it, I think, thanks.
This snippet I saw like 50 times today)))

Again, I know you’re just playing around and that’s a good thing. But I hope you’re developing a sense of when it’s a good time to use map() vs forEach() vs filter() vs reduce(), etc.

For this problem, map() is the most correct one*, and it makes the logic easy to follow when reading the code (professionally, you read a lot more code than you write). You certainly can use forEach(), but it’s awkward. One of those “just because you can doesn’t mean you should” kind of things.

* because we have a list, and want to apply a transform to each item in the list, and use the resultant list of transformed items

2 Likes

I think I am getting there, but it’s just a start. For example, I’ve never used filter yet I think(well, in some challenge steps, but that’s it). In general, if I see 2 or more options to choose implementation, I am trying to figure out what’s best.

1 Like

By the way, I have some topic and there are 3 questions like ‘which of 2 options is the best’.
If you have time, would you be so kind to take a look? I refer only to the last post, where is working solution.
It’s here