jQuery selectors always return an object whether an element is matched or not.
What you've effectively got is:
if (new Object())
item_id[category] = $(this).attr("id");
else
item_id.splice(category, 1);
Objects are always truthy (no matter if it's an empty object, or an object John Resig initialized), so this if statement will never execute the else.
What you're probably after is:
if ($('input[name="'+category+'"]:checked').length)
item_id[category] = $(this).attr("id");
else
item_id.splice(category, 1);
Which checks the length property instead.
This still won't work however, as splice() will shift all elements in your array; making the category wrong.
If your binding the event on a number of checkbox elements, it will be unwise to use .bind() (and it's counterparts .click()), as this method will bind an event for each checkbox. Instead, use .live(), or .delegate(); this will bind one event to an ancestor of all checkbox elements, and listen for event (using JavaScripts event bubbling), which is much more efficient.
Taking both of these points into consideration, you might fancy something like this.
$(yourJquerySelector).live('change', function () {
var category = '?' // (this.value ?)
item_id[category] = this.checked ? this.id : undefined;
});
item_iddefinitely an array, and iscategorydefinitely an integer?