Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Bash associative array ordering

If I wanted to pass the keys and values of an associative array in bash separately, and used something like

./foo.py -k "${!args[@]}" -v "${args[@]}"

would they come out in the same order? I don't really care what other the k=v pairs are stored in, but I do need to know if I could count on the keys and values coming out such that the 3rd item in the key array is in fact the key for the 3rd item in the value array.

I know that associative arrays are "unordered" and that whatever order you add them to the array is irrelevant to how they're output, but I'm wondering if the underlying storage behavior means they will always output in the same order.

like image 706
cosmic_cow_ck Avatar asked Dec 19 '16 20:12

cosmic_cow_ck


1 Answers

It appears that the answer is yes, the keys and values will always be in the same order, based on the code I found in Bash version 4.3, assoc.c, available here. The keys and values of the array are retrieved by the functions assoc_keys_to_word_list and assoc_to_word_list, respectively. Both of these functions delegate to assoc_to_word_list_internal, which runs the same loop in both cases, and only differentiates the type of item being retreived based on the t parameter (lines 482-503):

static WORD_LIST *
assoc_to_word_list_internal (h, t)
     HASH_TABLE *h;
     int t;
{
  WORD_LIST *list;
  int i;
  BUCKET_CONTENTS *tlist;
  char *w;

  if (h == 0 || assoc_empty (h))
    return((WORD_LIST *)NULL);
  list = (WORD_LIST *)NULL;

  for (i = 0; i < h->nbuckets; i++)
    for (tlist = hash_items (i, h); tlist; tlist = tlist->next)
      {
  w = (t == 0) ? (char *)tlist->data : (char *)tlist->key;
  list = make_word_list (make_bare_word(w), list);
      }
  return (REVERSE_LIST(list, WORD_LIST *));
}

In case you are wondering, make_word_list is defined in array.c/h. It just appends a new WORD_LIST node to the existing linked list.

While this provides no contractual guarantee that the behavior you expect will always be supported, it is a pretty good indication that you can use your calling convention safely, at least for now. The fact that associative arrays are Bash-only makes the implementation more of a valid reference.

like image 116
Mad Physicist Avatar answered Sep 21 '22 19:09

Mad Physicist