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)