Removing empty strings from a list

16 views
Skip to first unread message

Karl Auer

unread,
Dec 18, 2018, 2:47:30 AM12/18/18
to ansible-project
I am trying to build a list of names from a list of objects. It works fine, but some of the objects don't have a name. No problem, I use the default() filter to set those elements of my list to empty strings, like this:
  
# Build a list of names from a list of things
- set_fact:
     names: "{{ names |default([]) + [ item.name |default('') ] }}"
  with_items: "{{ things }}"

This got me, as expected, this result (because at the moment, my test list of things has two items, and neither has a name attribute):

ok: [localhost] => {
    "names": [
        "",
        ""
    ]
}


Now, how can I remove those empty strings from my list? I have read numerous articles that mention "rejectattr", but I don't understand how to use it.

I tried this:

# Remove any empty elements from the list of instance profile names
- set_fact:
     names: "{{ names |default([]) |reject('equalto', '') }}"


And got this mystifying  output:

ok: [localhost] => {
    "names": "<generator object _select_or_reject at 0x7f4ecd9c9aa0>"
}

I also tried using rejectattr on the first loop like this:

# Build a list of names from a list of things
- set_fact:
     names: "{{ names |default([]) + [ item.name |default('') ] }}"
  with_items: "{{ things |rejectattr('name', 'undefined') }}"

That got me a list with ONE empty string:

ok: [localhost] => {
    "names": [
        ""
    ]
}

Grateful for any pointers...

Regards, K.

PS: Pointers to USEFUL, COMPLETE examples of how to use rejectattr(), reject() and so on would be useful too. All the examples I have found seem to assume a huge amount of knowledge I don't have, or are tiny fragments of code...


--
Karl Auer

Email  : ka...@2pisoftware.com
Website: http://2pisoftware.com


GPG/PGP : 958A 2647 6C44 D376 3D63 86A5 FFB2 20BC 0257 5816
Previous: F0AB 6C70 A49D 1927 6E05 81E7 AD95 268F 2AB6 40EA

flowerysong

unread,
Dec 18, 2018, 4:27:42 AM12/18/18
to Ansible Project
On Tuesday, December 18, 2018 at 2:47:30 AM UTC-5, Karl Auer wrote:
I am trying to build a list of names from a list of objects. It works fine, but some of the objects don't have a name. No problem, I use the default() filter to set those elements of my list to empty strings, like this:
  
# Build a list of names from a list of things
- set_fact:
     names: "{{ names |default([]) + [ item.name |default('') ] }}"
  with_items: "{{ things }}"

This got me, as expected, this result (because at the moment, my test list of things has two items, and neither has a name attribute):

ok: [localhost] => {
    "names": [
        "",
        ""
    ]
}


Now, how can I remove those empty strings from my list? I have read numerous articles that mention "rejectattr", but I don't understand how to use it.

Well, the easiest way is not to put them in there in the first place.

- set_fact:
    names: "{{ things | selectattr('name', 'defined') | map(attribute='name') | list }}"
 
 
I tried this:

# Remove any empty elements from the list of instance profile names
- set_fact:
     names: "{{ names |default([]) |reject('equalto', '') }}"


And got this mystifying  output:

ok: [localhost] => {
    "names": "<generator object _select_or_reject at 0x7f4ecd9c9aa0>"
}

map(), select(), and friends return generators; use the list filter (as I've done above) to convert it to a list.

PS: Pointers to USEFUL, COMPLETE examples of how to use rejectattr(), reject() and so on would be useful too. All the examples I have found seem to assume a huge amount of knowledge I don't have, or are tiny fragments of code...

They're very simple filters, so useful, complete examples are going to *be* tiny fragments of code. http://jinja.pocoo.org/docs/latest/templates/#rejectattr

Karl Auer

unread,
Dec 18, 2018, 5:46:16 AM12/18/18
to ansible-project
Thanks, flowerysong.

I went with this:

- set_fact:
     names: []
- set_fact:
     names: "{{ names  + [ item.name ] }}"
  with_items: "{{ things |selectattr('name', 'defined') |list }}"

I want to have the list even if it is empty, that's why there are now two set_fact calls.

As far as the examples being complete, I have to disagree. These are ALL the examples for rejectattr() on the page you linked:
{{ users|rejectattr("is_active") }}
{{ users|rejectattr("email", "none") }}
Unanswered questions:
- what is "is_active"?
- what is "email"?
- what is "none"?
- what is "users"?
- what are the results of using the two examples?

This filter (like most of the others) needs far more complete documentation. It should provide a sample "users" variable, and sample output for the two examples. It should describe clearly what each of the possible parameters to the filter is.

I have no idea whether ANY of the following is correct:

I'm assuming that users is a structured list and that "is_active" and "email" are attributes of the elements of that list, e.g.:

vars:
   users:
      - name: Fred Nurk"
        email: fr...@example.com
        is_active: true
      - name: "Bob McBobson"
        email: b...@example.com
        is_active: false
      - name: "Mary Nurk"
        is_active: true

I'm also guessing that "none" is some sort of filter. It's described as a "test" - where are these tests documented? There is no description of it or link to other documentation, so I really have no idea. It may be selecting users where the email address is the literal string value "none".

Give the above sample "users" variable, I am guessing that the expected output of the two examples, if assigned to x, would be:

x:
   - name: "Fred Nurk"
     email: fr...@example.com
     is_active: true
   - name: "Mary Nurk"
     is_active: true

x:
     - name: Fred Nurk"
    email: fr...@example.com
     is_active: true
   - name: "Bob McBobson"
     email: b...@example.com
     is_active: false
Please don't just tell me I am free to write the documentation myself :-) This is constructive criticism, not a complaint.

Regards, K.


--
You received this message because you are subscribed to the Google Groups "Ansible Project" group.
To unsubscribe from this group and stop receiving emails from it, send an email to ansible-proje...@googlegroups.com.
To post to this group, send email to ansible...@googlegroups.com.
To view this discussion on the web visit https://groups.google.com/d/msgid/ansible-project/28329a51-bb25-4efc-be11-990ce9f7e9a1%40googlegroups.com.
For more options, visit https://groups.google.com/d/optout.
Reply all
Reply to author
Forward
0 new messages