0

How can I create a function count_word in order to get the result like this:

x = ['Hello', 'Bye']
print(count_word(x))
# Result must be [5, 3] 

without using len(x[index]) or any built-in function?

9
  • 2
    Create your own function(that will Iterate through the characters and increment the counter by one) and then do list(map(your_funtion, x)) . or [your_function(i) for i in x] Commented Mar 20, 2020 at 2:39
  • 5
    Why can't you use len or any other built-in function? Commented Mar 20, 2020 at 2:42
  • Odds are its an assignment for university or similar? Commented Mar 20, 2020 at 2:46
  • 1
    Define "built-in function". Commented Mar 20, 2020 at 20:49
  • 1
    docs.python.org/3/library/functions.html#built-in-functions Commented Mar 20, 2020 at 21:22

4 Answers 4

1

Since you're not allowed to use built-in functions, you have to iterate over each string in the list and over all characters of each word as well. Also you have to memorize the current length of each word and reset the counter if the next word is taken. This is done by re-assigning the counter value to 0 (length = 0) before the next inner iteration will be started:

def count_word(x):
    result = []
    for word in x:
        length = 0
        for char in word:
            length += 1
        result.append(length)
    return result

Please note that this is probably the no-brainer par excellence. However, Python offers some interesting other approaches to solve this problem. Here are some other interesting examples, which of course need to be adapted.


While this should answer your questions, I would like to add some notes about performance and why it is better to use built-in functions:

Generally spoken, built-in functions are doing the iteration under the hood for you or are even faster by e.g. simply getting the array’s length from the CPython list head structure (emphasis mine):

How are lists implemented in CPython?

CPython’s lists are really variable-length arrays, not Lisp-style linked lists. The implementation uses a contiguous array of references to other objects, and keeps a pointer to this array and the array’s length in a list head structure.

This makes indexing a list a[i] an operation whose cost is independent of the size of the list or the value of the index.

When items are appended or inserted, the array of references is resized. Some cleverness is applied to improve the performance of appending items repeatedly; when the array must be grown, some extra space is allocated so the next few times don’t require an actual resize.

(Credits also to Ken Y-N, see How does len(array) work under the hood)

Generally, it is better to use built-in functions whenever you can, because you seldom can beat the performance of the underlying implementation (e.g. for C-based Python installations):

def count_word_2(x):
    return [len(word) for word in x]

You can see that if you time the two given functions:

In [1]: from timeit import timeit

In [2]: statement = 'count_word(["Hello", "Bye"])'

In [3]: count_word_1 = """
   ...: def count_word(x):
   ...:     result = []
   ...:     for word in x:
   ...:         length = 0
   ...:         for char in word:
   ...:             length += 1
   ...:         result.append(length)
   ...:     return result
   ...: """

In [4]: count_word_2 = """
   ...: def count_word(x):
   ...:     return [len(word) for word in x]
   ...: """

In [5]: timeit(stmt=statement, setup=count_word_1, number=10000000)
Out[5]: 4.744415309000033

In [6]: timeit(stmt=statement, setup=count_word_2, number=10000000)
Out[6]: 2.7576589090022026

If also a little bit of cheating is allowed (using string dunder method __len()__ instead of built-in function len()), you can get some performance back (credits to HeapOverflow):

In [7]: count_word_3 = """
...: def count_word(x):
...:     return [word.__len__() for word in x]
...: """

In [8]: timeit(stmt=statement, setup=count_word_3, number=10000000)
Out[8]: 3.313732603997778

So a good rule of thumb is: Do whatever you can with built-in functions. They are more readable and faster.

Sign up to request clarification or add additional context in comments.

Comments

1

Another possibility using inline assignment (Python >= 3.8)

def count(word):
    c = 0
    return [[_ for _ in word if (c := c+1)], c][1]

words = ['Hello', 'How are you', 'Bye!']

>>> [count(w) for w in words]
[5, 11, 4]

Or even passing c as an input argument (defaulted to 0) could be used as an accumulated result from previous counts:

def count(word, c=0):
    return [[_ for _ in word if (c := c+1)], c][1]

ctot = [0]
[ctot.append(count(w, ctot[-1])) for w in words]  # sort of equivalent to built-in 'reduce'

>>> ctot  # or ctot[1:] to ignore the first zero
[0, 5, 16, 20]

Comments

0
x = ['Hello', 'Bye']
results = []
for single_string in x:
    string_length = 0
    for i in single_string: string_length += 1
    results.append(string_length)
print(results)

2 Comments

Oh no, you used the print built-in function!
@HymnsForDisco I imagine if this is for a uni/college assignment or quiz, then you'll be asked to submit the function definition only, and therefore you'll not use print() anyway!
0
x = ['Hello', 'Bye']
def count(x):
    i=0
    for j in x:i+=1
    return i
print(list(map(count, x)))

1 Comment

Here you're using built-in functions list and map for getting the wanted result. It is clear that OP doesn't want to use any built-in functions.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.