Home > Enterprise >  Identify negative values in a list without corresponding positive values
Identify negative values in a list without corresponding positive values

Time:05-27

Given a list (or numpy array) containing elements of type float, I want to identify those negative elements that don't have a corresponding positive element.

Test cases:

[] => []
[10.] => []
[-10.] => [-10.]
[10., -10.] => []
[10., -10., -10.] => [-10.]
[10., -10., -10., 50., 100., -50.] => [-10.]
[10., -10., -10., 50., 100., -50., -200.] => [-10., -200.]
[10., -10., 200., 300., 400., 500., -200., -300., -10.] => [-10.]
[-100., -200., -300.] => [-100., -200., -300.]
[-100., 200., -300., 400., -200.] => [-100., -300.]

CodePudding user response:

Try with collections.Counter and a dictionary comprehension:

from collections import Counter

lst = [10, -10, -10, -10, 50, 100, -50, -200]
counter = Counter(lst)
output = list(Counter({k: v-counter.get(-k,0) for k, v in counter.items() if k<0}).elements())

>>> output
[-10, -10, -200]

CodePudding user response:

Given the parameters this can be solved using some simple loops

def filter_for_negs_with_no_pos(items):
    pos_numbers = []
    neg_numbers = []
    for item in items:
        if item >= 0:
            pos_numbers.append(item)
        else:
            neg_numbers.append(item)
    for pos_number in pos_numbers:
        if any(np.isclose(-1 * pos_number,neg_numbers)):
            neg_numbers.remove(-1 * pos_number)
    return neg_numbers

This uses np.isclose to determine if the values are close to each other and after the loops runs neg_numbers will have the correct values. This was run using the following tests

def test_empty_is_empty(self):
    items = []
    expected = []
    ret_val = filter_for_negs_with_no_pos(items)
    self.assertListEqual(expected,ret_val)
def test_pos_is_empty(self):
    items = [10.]
    expected = []
    ret_val = filter_for_negs_with_no_pos(items)
    self.assertListEqual(expected,ret_val)
def test_one_neg_is_same_neg(self):
    items = [-10.]
    expected = [-10.]
    ret_val = filter_for_negs_with_no_pos(items)
    self.assertListEqual(expected,ret_val)
def test_neg_and_pos_of_neg_is_empty(self):
    items = [10.,-10.]
    expected = []
    ret_val = filter_for_negs_with_no_pos(items)
    self.assertListEqual(expected,ret_val)
def test_two_neg_and_one_pos_is_one_neg(self):
    items = [10.,-10.,-10.]
    expected = [-10.]
    ret_val = filter_for_negs_with_no_pos(items)
    self.assertListEqual(expected,ret_val)
def test_two_neg_and_one_pos_is_one_neg_float(self):
    items = [10.43232,-10.43231,-10.43232]
    expected = [-10.43232]
    ret_val = filter_for_negs_with_no_pos(items)
    self.assertTrue(np.isclose(expected,ret_val).all())
def test_larger_set(self):
    items = [10, -10, -10, 50, 100, -50]
    mult_items = [
        [10., -10., -10., 50., 100., -50.],
        [10., -10., -10., 50., 100., -50., -200.],
        [10., -10., 200., 300., 400., 500., -200., -300., -10.],
        [-100., 200., -300., 400., -200.]
        
    ]
    expected = [
        [-10.],
        [-10.,-200.],
        [-10.],
        [-100.,-300.]
    ]
    for index,item in enumerate(mult_items):
        with self.subTest(item=item):
            ret_val = filter_for_negs_with_no_pos(item)
            self.assertListEqual(ret_val,expected[index])
        
def test_all_neg(self):
    items = [-100., -200., -300.]
    expected = [-100., -200., -300.]
    ret_val = filter_for_negs_with_no_pos(items)
    self.assertListEqual(expected,ret_val)
  • Related