import numpy as np
import nBiggest
import nSmallest

def findNBiggest(unsorted,n):
	"""Finds the n biggest elements in an unsorted list in a more memory efficient way

	"""

	biggest = np.sort(unsorted[:n])
	toSort = unsorted[n:]

	biggest = np.array(biggest,dtype=np.float64)
	toSort = np.array(toSort,dtype=np.float64)

	nBiggest.nbiggest(biggest,toSort)

	return biggest

def findNBiggestInds(unsorted,n):
	"""Finds the array indices of the n biggest elements in an unsorted list in a memory efficient way

	"""
	biggest = unsorted[:n]
	toSort = unsorted[n:]

	bigInds = np.argsort(biggest)
	biggest = biggest[bigInds]

	biggest = np.array(biggest,dtype=np.float64)
	toSort = np.array(toSort,dtype=np.float64)
	bigInds = np.array(bigInds,dtype=np.int)

	nBiggest.nbiggestinds(biggest,toSort,bigInds)

	return biggest, bigInds

def findNSmallest(unsorted,n):
	
	"""Finds the n smallest elements in an unsorted list in a more memory efficient way

	"""
		
	smallest = np.sort(unsorted[:n])
	toSort = unsorted[n:]

	smallest = np.array(smallest,dtype=np.float64)
	toSort = np.array(toSort,dtype=np.float64)

	nSmallest.nsmallest(smallest,toSort)

	return smallest

def findNSmallestInds(unsorted,n):
	"""Finds the array indices of the n smallest elements in an unsorted list in a memory efficient way

	"""
	smallest = unsorted[:n]
	toSort = unsorted[n:]

	smallInds = np.argsort(smallest)
	smallest = smallest[smallInds]

	smallest = np.array(smallest,dtype=np.float64)
	toSort = np.array(toSort,dtype=np.float64)
	smallInds = np.array(smallInds,dtype=np.int)

	nSmallest.nsmallestinds(smallest,toSort,smallInds)

	return smallest, smallInds

def mergeListsMin(list1,list2,preSorted=False):
	"""Takes two lists and returns a list (of the same length as list1) of the minimum of both lists

	"""

	if not preSorted:
		list1 = np.sort(list1)
	
	list1 = np.array(list1,dtype=np.float64)
	list2 = np.array(list2,dtype=np.float64)

	nSmallest.nsmallest(list1,list2)

	return list1

def mergeListsMax(list1,list2,preSorted=False):
	"""Takes two lists and returns a list (of the same length as list1) of the maximum of both lists

	"""

	if not preSorted:
		list1 = np.sort(list1)
	
	list1 = np.array(list1,dtype=np.float64)
	list2 = np.array(list2,dtype=np.float64)

	nBiggest.nbiggest(list1,list2)

	return list1

def mergeListsMinInds(list1,list2,preSorted=False):
	"""Takes two lists and returns the indices from each of them constitute the list that contains,
	the minimum of both of them (of length the same as list1), and also the smallest elements

	"""

	list1 = np.array(list1,dtype=np.float64)
	list2 = np.array(list2,dtype=np.float64)

	if not preSorted:
		list1inds = np.argsort(list1)
		list1 = list1[list1inds]

	list1inds = np.array(list1inds,dtype=np.int)
	
	nSmallest.nsmallestinds(list1,list2,list1inds)
	
	length = len(list1)	

	l1,l2 = [],[]
	for ind in list1inds:
		if ind < length:
			l1.append(ind)
		else:
			l2.append(ind - length)

	return list1,np.array(l1),np.array(l2)























	
