'Convert a list of observations into input & target tensors.'

def batchify(self, observations):

    exs = [ex for ex in observations if ('text' in ex)]
    valid_inds = [i for (i, ex) in enumerate(observations) if ('text' in ex)]
    batchsize = len(exs)
    xs = None
    if (batchsize > 0):
        parsed = [self.parse(ex['text']) for ex in exs]
        max_x_len = max([len(x) for x in parsed])
        xs = torch.LongTensor(batchsize, max_x_len).fill_(0)
        for (i, x) in enumerate(parsed):
            offset = (max_x_len - len(x))
            for (j, idx) in enumerate(x):
                xs[i][(j + offset)] = idx
        if self.use_cuda:
            xs = xs.cuda(async=True)
        xs = Variable(xs)
    ys = None
    if ((batchsize > 0) and any([('labels' in ex) for ex in exs])):
        labels = [((random.choice(ex.get('labels', [''])) + '    ') + self.END) for ex in exs]
        parsed = [self.parse(y) for y in labels]
        max_y_len = max((len(y) for y in parsed))
        ys = torch.LongTensor(batchsize, max_y_len).fill_(0)
        for (i, y) in enumerate(parsed):
            for (j, idx) in enumerate(y):
                ys[i][j] = idx
        if self.use_cuda:
            ys = ys.cuda(async=True)
        ys = Variable(ys)
    cands = None
    valid_cands = None
    if ((ys is None) and self.rank):
        parsed = []
        valid_cands = []
        for i in valid_inds:
            if ('label_candidates' in observations[i]):
                cs = list(observations[i]['label_candidates'])
                parsed.append([self.parse(c) for c in cs])
                valid_cands.append((i, cs))
        if (len(parsed) > 0):
            max_c_len = max((max((len(c) for c in cs)) for cs in parsed))
            max_c_cnt = max((len(cs) for cs in parsed))
            cands = torch.LongTensor(len(parsed), max_c_cnt, max_c_len).fill_(0)
            for (i, cs) in enumerate(parsed):
                for (j, c) in enumerate(cs):
                    for (k, idx) in enumerate(c):
                        cands[i][j][k] = idx
            if self.use_cuda:
                cands = cands.cuda(async=True)
            cands = Variable(cands)
    return (xs, ys, valid_inds, cands, valid_cands)
