RecyclableLongList.Compatibility.List.FindAll() implemented.
This commit is contained in:
1 parent
02153bea2a
commit
3e66504e09
2 files changed
+126
-52
No files matched your search
+23
-24
@@ -391,30 +391,6 @@ namespace Recyclable.CollectionsTests
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
[Theory]
|
|
||||||
[MemberData(nameof(RecyclableLongListTestData.ItemsCountTestCases), MemberType = typeof(RecyclableLongListTestData))]
|
|
||||||
public void FindAllShouldReturnCorrectIndexes(int itemsCount)
|
|
||||||
{
|
|
||||||
const int ExpectedItem = 1;
|
|
||||||
|
|
||||||
// Prepare
|
|
||||||
var testData = Enumerable.Range(0, itemsCount).Select(value => value % 2 == 0 ? ExpectedItem : -ExpectedItem);
|
|
||||||
using var list = new RecyclableLongList<int>(testData, initialCapacity: itemsCount);
|
|
||||||
|
|
||||||
// Act
|
|
||||||
using var actual = list.FindAll(x => x == ExpectedItem);
|
|
||||||
|
|
||||||
// Validate
|
|
||||||
var expectedData = testData.ToList().FindAll(x => x == ExpectedItem);
|
|
||||||
|
|
||||||
_ = actual.Count.Should().Be(expectedData.Count);
|
|
||||||
_ = actual.Should().Equal(expectedData);
|
|
||||||
if (expectedData.Count > 0)
|
|
||||||
{
|
|
||||||
_ = actual.Should().AllSatisfy(x => x.Should().Be(ExpectedItem)).And.Equal(expectedData);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
[Theory]
|
[Theory]
|
||||||
[MemberData(nameof(RecyclableLongListTestData.ItemsCountTestCases), MemberType = typeof(RecyclableLongListTestData))]
|
[MemberData(nameof(RecyclableLongListTestData.ItemsCountTestCases), MemberType = typeof(RecyclableLongListTestData))]
|
||||||
public void FindAllShouldNotFindNonExistingItems(int itemsCount)
|
public void FindAllShouldNotFindNonExistingItems(int itemsCount)
|
||||||
@@ -435,6 +411,29 @@ namespace Recyclable.CollectionsTests
|
|||||||
_ = foundItems.Should().Equal(expectedData);
|
_ = foundItems.Should().Equal(expectedData);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[Theory]
|
||||||
|
[MemberData(nameof(RecyclableLongListTestData.ItemsCountTestCases), MemberType = typeof(RecyclableLongListTestData))]
|
||||||
|
public void FindAllShouldReturnCorrectIndexes(int itemsCount)
|
||||||
|
{
|
||||||
|
const int ExpectedItem = 1;
|
||||||
|
|
||||||
|
// Prepare
|
||||||
|
var testData = Enumerable.Range(0, itemsCount).Select(value => value % 2 == 0 ? ExpectedItem : -ExpectedItem);
|
||||||
|
using var list = new RecyclableLongList<int>(testData, initialCapacity: itemsCount);
|
||||||
|
var expectedData = testData.ToList().FindAll(x => x == ExpectedItem);
|
||||||
|
|
||||||
|
// Act
|
||||||
|
using var actual = list.FindAll(x => x == ExpectedItem);
|
||||||
|
|
||||||
|
// Validate
|
||||||
|
_ = actual.Count.Should().Be(expectedData.Count);
|
||||||
|
_ = actual.Should().Equal(expectedData);
|
||||||
|
if (expectedData.Count > 0)
|
||||||
|
{
|
||||||
|
_ = actual.Should().AllSatisfy(x => x.Should().Be(ExpectedItem)).And.Equal(expectedData);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
[Theory]
|
[Theory]
|
||||||
[MemberData(nameof(RecyclableLongListTestData.SourceDataWithItemIndexVariants), MemberType = typeof(RecyclableLongListTestData))]
|
[MemberData(nameof(RecyclableLongListTestData.SourceDataWithItemIndexVariants), MemberType = typeof(RecyclableLongListTestData))]
|
||||||
public void FindIndexShouldReturnCorrectIndexes(string testCase, IEnumerable<long> testData, int itemsCount, in long[] itemIndexes)
|
public void FindIndexShouldReturnCorrectIndexes(string testCase, IEnumerable<long> testData, int itemsCount, in long[] itemIndexes)
|
||||||
|
|||||||
+103
-28
@@ -1,5 +1,7 @@
|
|||||||
// Ignore Spelling: zzz
|
// Ignore Spelling: zzz
|
||||||
|
|
||||||
|
using System.Numerics;
|
||||||
|
|
||||||
namespace Recyclable.Collections
|
namespace Recyclable.Collections
|
||||||
{
|
{
|
||||||
#pragma warning disable IDE1006 // This intentional so that it shows at the end of IntelliSense list
|
#pragma warning disable IDE1006 // This intentional so that it shows at the end of IntelliSense list
|
||||||
@@ -81,41 +83,114 @@ namespace Recyclable.Collections
|
|||||||
throw new NotImplementedException();
|
throw new NotImplementedException();
|
||||||
}
|
}
|
||||||
|
|
||||||
public static RecyclableList<T> FindAll<T>(this RecyclableLongList<T> list, Predicate<T> match)
|
public static RecyclableLongList<T> FindAll<T>(this RecyclableLongList<T> list, Predicate<T> match)
|
||||||
{
|
{
|
||||||
//int sourceItemsCount = list._count;
|
if (list._longCount == 0)
|
||||||
//if (sourceItemsCount == 0)
|
{
|
||||||
//{
|
return new();
|
||||||
// return new();
|
}
|
||||||
//}
|
|
||||||
|
|
||||||
//ReadOnlySpan<T> sourceSpan = list._memoryBlock;
|
int sourceBlockIndex = 0,
|
||||||
//RecyclableList<T> result = new(sourceItemsCount >> 3);
|
blockSize = list._blockSize,
|
||||||
//Span<T> resultSpan = result._memoryBlock;
|
targetBlockIndex = 0;
|
||||||
//int capacity = result._capacity,
|
var targetCapacity = Math.Max(list._longCount >> 3, RecyclableDefaults.InitialCapacity);
|
||||||
// resultItemsCount = 0;
|
if (!BitOperations.IsPow2(targetCapacity))
|
||||||
|
{
|
||||||
|
targetCapacity = checked((long)BitOperations.RoundUpToPowerOf2((ulong)targetCapacity));
|
||||||
|
}
|
||||||
|
|
||||||
//for (var itemIndex = 0; itemIndex < sourceItemsCount; itemIndex++)
|
RecyclableLongList<T> result = new(blockSize, targetCapacity);
|
||||||
//{
|
ReadOnlySpan<T[]> resultMemoryBlocksSpan = result._memoryBlocks;
|
||||||
// if (match(sourceSpan[itemIndex]))
|
Span<T> resultMemoryBlockSpan = resultMemoryBlocksSpan[0];
|
||||||
// {
|
ReadOnlySpan<T[]> sourceMemoryBlocksSpan = list._memoryBlocks;
|
||||||
// if (resultItemsCount + 1 > capacity)
|
ReadOnlySpan<T> sourceMemoryBlockSpan = sourceMemoryBlocksSpan[0];
|
||||||
// {
|
var sourceItemIndex = 0;
|
||||||
// capacity = checked((int)BitOperations.RoundUpToPowerOf2((uint)resultItemsCount + 1));
|
int lastBlockWithData = list._lastBlockWithData;
|
||||||
// _ = RecyclableListHelpers<T>.EnsureCapacity(result, resultItemsCount, capacity);
|
var targetItemIndex = 0;
|
||||||
// resultSpan = result._memoryBlock;
|
var fullBlocksItemsCount = 0L;
|
||||||
// }
|
while (sourceBlockIndex < lastBlockWithData)
|
||||||
|
{
|
||||||
|
var item = sourceMemoryBlockSpan[sourceItemIndex];
|
||||||
|
if (match(item))
|
||||||
|
{
|
||||||
|
if (fullBlocksItemsCount + targetItemIndex >= targetCapacity)
|
||||||
|
{
|
||||||
|
targetCapacity = RecyclableLongList<T>.Helpers.Resize(result, blockSize, result._blockSizePow2BitShift, targetCapacity << 1);
|
||||||
|
resultMemoryBlocksSpan = new(list._memoryBlocks);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (targetItemIndex == blockSize)
|
||||||
|
{
|
||||||
|
targetItemIndex = 0;
|
||||||
|
resultMemoryBlockSpan = resultMemoryBlocksSpan[++targetBlockIndex];
|
||||||
|
fullBlocksItemsCount += blockSize;
|
||||||
|
}
|
||||||
|
|
||||||
// resultSpan[resultItemsCount++] = sourceSpan[itemIndex];
|
resultMemoryBlockSpan[targetItemIndex++] = item;
|
||||||
// }
|
}
|
||||||
//}
|
|
||||||
|
|
||||||
//result._capacity = capacity;
|
if (sourceItemIndex + 1 == blockSize)
|
||||||
//result._count = resultItemsCount;
|
{
|
||||||
//return result;
|
sourceItemIndex = 0;
|
||||||
|
sourceBlockIndex++;
|
||||||
|
sourceMemoryBlockSpan = sourceMemoryBlocksSpan[sourceBlockIndex];
|
||||||
|
|
||||||
throw new NotImplementedException();
|
if (sourceBlockIndex == lastBlockWithData)
|
||||||
|
{
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
sourceItemIndex++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (sourceBlockIndex == lastBlockWithData)
|
||||||
|
{
|
||||||
|
// We're re-using another variable for better performance
|
||||||
|
lastBlockWithData = list._nextItemIndex > 0 ? list._nextItemIndex : blockSize;
|
||||||
|
while (sourceItemIndex < lastBlockWithData)
|
||||||
|
{
|
||||||
|
var item = sourceMemoryBlockSpan[sourceItemIndex++];
|
||||||
|
if (match(item))
|
||||||
|
{
|
||||||
|
if (fullBlocksItemsCount + targetItemIndex >= targetCapacity)
|
||||||
|
{
|
||||||
|
targetCapacity = RecyclableLongList<T>.Helpers.Resize(result, blockSize, result._blockSizePow2BitShift, targetCapacity << 1);
|
||||||
|
resultMemoryBlocksSpan = new(list._memoryBlocks);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (targetItemIndex == blockSize)
|
||||||
|
{
|
||||||
|
targetItemIndex = 0;
|
||||||
|
resultMemoryBlockSpan = resultMemoryBlocksSpan[++targetBlockIndex];
|
||||||
|
fullBlocksItemsCount += blockSize;
|
||||||
|
}
|
||||||
|
|
||||||
|
resultMemoryBlockSpan[targetItemIndex++] = item;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (targetItemIndex == blockSize)
|
||||||
|
{
|
||||||
|
result._nextItemBlockIndex = targetBlockIndex + 1;
|
||||||
|
result._nextItemIndex = 0;
|
||||||
|
result._lastBlockWithData = targetBlockIndex;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
result._nextItemBlockIndex = targetBlockIndex;
|
||||||
|
result._nextItemIndex = targetItemIndex;
|
||||||
|
result._lastBlockWithData = targetBlockIndex;
|
||||||
|
}
|
||||||
|
|
||||||
|
result._longCount = fullBlocksItemsCount + targetItemIndex;
|
||||||
|
result._capacity = targetCapacity;
|
||||||
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static RecyclableList<int> FindAllIndexes<T>(this RecyclableLongList<T> list, Predicate<T> match)
|
public static RecyclableList<int> FindAllIndexes<T>(this RecyclableLongList<T> list, Predicate<T> match)
|
||||||
{
|
{
|
||||||
//int sourceItemsCount = list._count;
|
//int sourceItemsCount = list._count;
|
||||||
|
|||||||
Reference in new issue
Block a user