Skip to content

Commit 144fc70

Browse files
committed
Попытка исправить неиндексированный поиск в ТЗ методом Найти
1 parent 7222683 commit 144fc70

File tree

4 files changed

+233
-163
lines changed

4 files changed

+233
-163
lines changed
Lines changed: 136 additions & 131 deletions
Original file line numberDiff line numberDiff line change
@@ -1,148 +1,153 @@
1-
/*----------------------------------------------------------
2-
This Source Code Form is subject to the terms of the
3-
Mozilla Public License, v.2.0. If a copy of the MPL
4-
was not distributed with this file, You can obtain one
5-
at http://mozilla.org/MPL/2.0/.
6-
----------------------------------------------------------*/
7-
8-
using System.Collections.Generic;
9-
using System.Linq;
10-
using OneScript.Contexts;
11-
using OneScript.Exceptions;
12-
using OneScript.Values;
13-
using ScriptEngine.Machine;
14-
using ScriptEngine.Machine.Contexts;
15-
16-
namespace OneScript.StandardLibrary.Collections.Indexes
17-
{
18-
[ContextClass("ИндексКоллекции", "CollectionIndex")]
19-
public class CollectionIndex : AutoCollectionContext<CollectionIndex, IValue>
20-
{
21-
private readonly List<IValue> _fields = new List<IValue>();
22-
private readonly IIndexCollectionSource _source;
23-
24-
private readonly Dictionary<CollectionIndexKey, HashSet<IValue>> _data =
25-
new Dictionary<CollectionIndexKey, HashSet<IValue>>();
26-
27-
public CollectionIndex(IIndexCollectionSource source, IEnumerable<IValue> fields)
28-
{
29-
foreach (var field in fields)
1+
/*----------------------------------------------------------
2+
This Source Code Form is subject to the terms of the
3+
Mozilla Public License, v.2.0. If a copy of the MPL
4+
was not distributed with this file, You can obtain one
5+
at http://mozilla.org/MPL/2.0/.
6+
----------------------------------------------------------*/
7+
8+
using System.Collections.Generic;
9+
using System.Linq;
10+
using OneScript.Contexts;
11+
using OneScript.Exceptions;
12+
using OneScript.Values;
13+
using ScriptEngine.Machine;
14+
using ScriptEngine.Machine.Contexts;
15+
16+
namespace OneScript.StandardLibrary.Collections.Indexes
17+
{
18+
[ContextClass("ИндексКоллекции", "CollectionIndex")]
19+
public class CollectionIndex : AutoCollectionContext<CollectionIndex, IValue>
20+
{
21+
private readonly List<IValue> _fields = new List<IValue>();
22+
private readonly IIndexCollectionSource _source;
23+
24+
private readonly Dictionary<CollectionIndexKey, HashSet<IValue>> _data =
25+
new Dictionary<CollectionIndexKey, HashSet<IValue>>();
26+
27+
public CollectionIndex(IIndexCollectionSource source, IEnumerable<IValue> fields)
28+
{
29+
foreach (var field in fields)
3030
{
3131
if (field is ValueTable.ValueTableColumn column)
3232
column.AddToIndex();
3333
_fields.Add(field);
34-
}
35-
36-
_source = source;
37-
foreach (var value in _source)
38-
{
39-
ElementAdded(value);
4034
}
41-
}
42-
43-
internal bool CanBeUsedFor(IEnumerable<IValue> searchFields)
44-
{
45-
return _fields.Count != 0 && _fields.All(f => searchFields.Contains(f));
46-
}
47-
48-
private CollectionIndexKey IndexKey(PropertyNameIndexAccessor source)
49-
{
50-
return CollectionIndexKey.Extract(source, _fields);
51-
}
52-
53-
public override string ToString()
54-
{
55-
return string.Join(", ", _fields.Select(field => _source.GetName(field)));
56-
}
57-
58-
public IEnumerable<IValue> GetData(PropertyNameIndexAccessor searchCriteria)
59-
{
60-
var key = IndexKey(searchCriteria);
61-
return _data.TryGetValue(key, out var filteredData) ? filteredData : Enumerable.Empty<IValue>();
62-
}
63-
64-
internal void FieldRemoved(IValue field)
65-
{
66-
if (_fields.Contains(field))
67-
{
35+
36+
_source = source;
37+
foreach (var value in _source)
38+
{
39+
ElementAdded(value);
40+
}
41+
}
42+
43+
internal bool CanBeUsedFor(IEnumerable<IValue> searchFields)
44+
{
45+
return _fields.Count != 0 && _fields.All(f => searchFields.Contains(f));
46+
}
47+
48+
/// <summary>
49+
/// Поля, входящие в индекс (в порядке объявления индекса).
50+
/// </summary>
51+
internal IReadOnlyList<IValue> GetIndexedFields() => _fields;
52+
53+
private CollectionIndexKey IndexKey(PropertyNameIndexAccessor source)
54+
{
55+
return CollectionIndexKey.Extract(source, _fields);
56+
}
57+
58+
public override string ToString()
59+
{
60+
return string.Join(", ", _fields.Select(field => _source.GetName(field)));
61+
}
62+
63+
public IEnumerable<IValue> GetData(PropertyNameIndexAccessor searchCriteria)
64+
{
65+
var key = IndexKey(searchCriteria);
66+
return _data.TryGetValue(key, out var filteredData) ? filteredData : Enumerable.Empty<IValue>();
67+
}
68+
69+
internal void FieldRemoved(IValue field)
70+
{
71+
if (_fields.Contains(field))
72+
{
6873
while (_fields.Contains(field))
6974
{
7075
if (field is ValueTable.ValueTableColumn column)
7176
column.DeleteFromIndex();
7277

7378
_fields.Remove(field);
74-
}
75-
Rebuild();
76-
}
77-
}
78-
79+
}
80+
Rebuild();
81+
}
82+
}
83+
7984
internal void ExcludeFields()
8085
{
81-
foreach (var field in _fields)
86+
foreach (var field in _fields)
8287
{
8388
if (field is ValueTable.ValueTableColumn column)
8489
column.DeleteFromIndex();
8590
}
86-
}
87-
88-
internal void ElementAdded(PropertyNameIndexAccessor element)
89-
{
90-
var key = CollectionIndexKey.Extract(element, _fields);
91-
if (_data.TryGetValue(key, out var set))
92-
{
93-
set.Add(element);
94-
}
95-
else
96-
{
97-
_data.Add(key, new HashSet<IValue> { element });
98-
}
99-
}
100-
101-
internal void ElementRemoved(PropertyNameIndexAccessor element)
102-
{
103-
var key = CollectionIndexKey.Extract(element, _fields);
104-
if (_data.TryGetValue(key, out var set))
105-
{
106-
set.Remove(element);
107-
}
108-
}
109-
110-
internal void Clear() => _data.Clear();
111-
112-
internal void Rebuild()
113-
{
114-
_data.Clear();
115-
foreach (var value in _source)
116-
{
117-
ElementAdded(value);
118-
}
119-
}
120-
121-
public override IValue GetIndexedValue(IValue index)
122-
{
123-
if (index is BslNumericValue numericValue)
124-
{
125-
var numeric = numericValue.AsNumber();
126-
if (numeric >= 0 && numeric < _fields.Count)
127-
{
128-
129-
return ValueFactory.Create(_source.GetName(_fields[decimal.ToInt32(numeric)]));
130-
}
131-
}
132-
throw RuntimeException.InvalidArgumentValue();
133-
}
134-
135-
public override int Count()
136-
{
137-
return _fields.Count;
138-
}
139-
140-
public override IEnumerator<IValue> GetEnumerator()
141-
{
142-
foreach (var field in _fields)
143-
{
144-
yield return ValueFactory.Create(_source.GetName(field));
145-
}
146-
}
147-
}
148-
}
91+
}
92+
93+
internal void ElementAdded(PropertyNameIndexAccessor element)
94+
{
95+
var key = CollectionIndexKey.Extract(element, _fields);
96+
if (_data.TryGetValue(key, out var set))
97+
{
98+
set.Add(element);
99+
}
100+
else
101+
{
102+
_data.Add(key, new HashSet<IValue> { element });
103+
}
104+
}
105+
106+
internal void ElementRemoved(PropertyNameIndexAccessor element)
107+
{
108+
var key = CollectionIndexKey.Extract(element, _fields);
109+
if (_data.TryGetValue(key, out var set))
110+
{
111+
set.Remove(element);
112+
}
113+
}
114+
115+
internal void Clear() => _data.Clear();
116+
117+
internal void Rebuild()
118+
{
119+
_data.Clear();
120+
foreach (var value in _source)
121+
{
122+
ElementAdded(value);
123+
}
124+
}
125+
126+
public override IValue GetIndexedValue(IValue index)
127+
{
128+
if (index is BslNumericValue numericValue)
129+
{
130+
var numeric = numericValue.AsNumber();
131+
if (numeric >= 0 && numeric < _fields.Count)
132+
{
133+
134+
return ValueFactory.Create(_source.GetName(_fields[decimal.ToInt32(numeric)]));
135+
}
136+
}
137+
throw RuntimeException.InvalidArgumentValue();
138+
}
139+
140+
public override int Count()
141+
{
142+
return _fields.Count;
143+
}
144+
145+
public override IEnumerator<IValue> GetEnumerator()
146+
{
147+
foreach (var field in _fields)
148+
{
149+
yield return ValueFactory.Create(_source.GetName(field));
150+
}
151+
}
152+
}
153+
}

src/OneScript.StandardLibrary/Collections/ValueTable/CollectionIndexes.cs

Lines changed: 28 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
/*----------------------------------------------------------
1+
/*----------------------------------------------------------
22
This Source Code Form is subject to the terms of the
33
Mozilla Public License, v.2.0. If a copy of the MPL
44
was not distributed with this file, You can obtain one
@@ -134,6 +134,30 @@ public CollectionIndex FindSuitableIndex(IEnumerable<IValue> searchFields)
134134
return _indexes.FirstOrDefault(index => index.CanBeUsedFor(searchFields));
135135
}
136136

137+
/// <summary>
138+
/// Индекс, все поля которого содержатся в <paramref name="searchColumns"/>,
139+
/// с максимальным числом полей (более узкий состав ключа — предпочтительнее).
140+
/// </summary>
141+
public CollectionIndex FindBestContainedIndex(IEnumerable<IValue> searchColumns)
142+
{
143+
CollectionIndex best = null;
144+
var bestFieldCount = -1;
145+
foreach (var index in _indexes)
146+
{
147+
if (!index.CanBeUsedFor(searchColumns))
148+
continue;
149+
150+
var n = index.Count();
151+
if (n > bestFieldCount)
152+
{
153+
bestFieldCount = n;
154+
best = index;
155+
}
156+
}
157+
158+
return best;
159+
}
160+
137161
private static List<IValue> BuildFieldList(IIndexCollectionSource source, string fieldList)
138162
{
139163
var fields = new List<IValue>();
@@ -142,9 +166,9 @@ private static List<IValue> BuildFieldList(IIndexCollectionSource source, string
142166

143167
var fieldNames = fieldList.Split(',', System.StringSplitOptions.RemoveEmptyEntries);
144168
foreach (var fieldName in fieldNames)
145-
{
146-
var name = fieldName.Trim();
147-
var field = source.GetField(name) ?? throw ColumnException.WrongColumnName(fieldName);
169+
{
170+
var name = fieldName.Trim();
171+
var field = source.GetField(name) ?? throw ColumnException.WrongColumnName(fieldName);
148172
fields.Add(field);
149173
}
150174

0 commit comments

Comments
 (0)