У меня есть словарь, в котором значения хранятся в следующем формате:
userID, empDetails
Например,
1234, 'empName,jobDesc,CardNumber,Type'
Я должен сравнить эту информацию с другим набором информации таким образом, что -
Первое условие простое и может быть выполнено
dictionary.Remove(key)
Но я не понимаю, как реализовать второе условие. я хочу что-то вроде
if (CardNumber.PresentinAboveDictionary)
then
Remove that record
Я знаю, что мы можем сравнить неполную строку в таком ключе, но я хочу удалить запись. Проверить, содержит ли какая-либо часть значения хеш-таблицы определенную строку c#
@NitinSawant их будет около тысячи.
лучше использовать другую эффективную структуру данных.
Вас беспокоит производительность или вам просто нужно работающее решение?
@SBFrancies Первое предпочтение будет рабочим решением, но да, производительность также является важным фактором.





вы можете сделать что-то вроде этого.
var recordsToRemove = dictionary.Where(x => x.Value.Contains("what you are looking for"))
.ToList();
if (recordsToRemove.Any())
{
foreach (var record in recordsToRemove)
{
dictionary.Remove(record.Key);
}
}
Предполагая, что сведения о занятости в вашем словаре представляют собой строку в указанном формате, вам необходимо:
Пример кода решения:
var dictionary = new Dictionary<int, string>() { { 1, "empName,jobDesc,124124134,Type" } };
var cardNumber = 124124134;
var entry = dictionary.FirstOrDefault(x => DoEmploymentDetailsContainCardNumber(x.Value, cardNumber));
if (!entry.Equals(default(KeyValuePair<int, string>)))
{
dictionary.Remove(entry.Key);
}
Метод, который проверяет, присутствует ли номер карты в реквизитах занятости:
private static bool DoEmploymentDetailsContainCardNumber(string empDetails, int cardNumber)
{
var splitEmpDetails = empDetails.Split(',');
var empDetailsCardNumber = splitEmpDetails[2];
return empDetailsCardNumber == cardNumber.ToString();
}
вы повторяете все элементы и применяете разделение ко всем, а затем сравниваете, что занимает больше времени, если есть тысячи элементов
Дольше чего?
Это решение не принимает во внимание возможность того, что номера карт могут быть неуникальными - может быть, они всегда уникальны, но, насколько я могу судить, спрашивающий не указывает это.
@SBFrancies Это подразумевается языком, использованным в вопросе, иначе грамматика неверна.
Вместо Dictionary вы можете использовать строго типизированный List
RemoveParallel.ForEach, повторите список и удалите элемент (осторожно, это займет больше времени)псевдокод:
using System;
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.Threading.Tasks;
using System.Linq;
using System.Collections;
namespace ConsoleApp4
{
public class Employee
{
public Employee(int userID, string empDetails)
{
string[] props = empDetails.Split(new char[] { ',' }, StringSplitOptions.None);
this.userID = userID;
this.empName = props[0];
this.jobDesc = props[1];
this.CardNumber = props[2];
this.Type = props[3];
}
public int userID { get; set; }
public string empName { get; set; }
public string jobDesc { get; set; }
public string CardNumber { get; set; }
public string Type { get; set; }
}
public class MyCustomList : List<Employee>
{
public void Add(int userID, string empDetails)
{
this.Add(new Employee(userID, empDetails));
}
public bool Remove(string CardNumber)
{
bool found = false ;
Parallel.ForEach(this,
(i, state) =>
{
if (i.CardNumber == CardNumber)
{
this.Remove(i);
state.Break();
}
});
return found;
}
public bool RemoveV2(string CardNumber)
{
bool found = false;
if (this.Any(x => x.CardNumber == CardNumber))
{
this.Remove(this.Where(x => x.CardNumber == CardNumber).First());
found = true;
}
return found;
}
}
class Program
{
static void Main(string[] args)
{
var dict = new MyCustomList();//userID, empDetails list
dict.Add(12341, "empName1,jobDesc,CardNumber1,Type");
dict.Add(12342, "empName2,jobDesc,CardNumber2,Type");
dict.Add(12343, "empName3,jobDesc,CardNumber3,Type");
dict.Add(12344, "empName4,jobDesc,CardNumber4,Type");
dict.Add(12345, "empName5,jobDesc,CardNumber5,Type");
dict.Add(12346, "empName6,jobDesc,CardNumber6,Type");
dict.Add(12347, "empName7,jobDesc,CardNumber7,Type");
dict.Add(12348, "empName8,jobDesc,CardNumber8,Type");
//remove CardNumber5
dict.Remove("CardNumber5");
Console.Write(dict);
}
}
}
вы можете следовать простому подходу, чтобы удалить ключ, используя здесь цикл.
Здесь я предполагаю, что в словаре нет ключа со значением -1.
int keyToRemove = -1;
foreach (var entry in dictionary)
{
if (entry.Value.Contains(CardNumber))
{
keyToRemove = entry.Key;
break;
}
}
if (keyToRemove != -1)
{
dictionary.Remove(keyToRemove);
}
Это, возможно, излишне и не оптимизировано для многократного чтения полного набора данных, но это значительно быстрее, чем принятое решение. Я собрал тест решения ниже, который сделал следующее:
Сгенерировано 1 000 000 строк данных с уникальными идентификаторами и номерами карт (решение сработало бы и в том случае, если бы номера карт не были уникальными)
Случайным образом удалено 100 000 элементов данных по идентификатору и 100 000 элементов данных по номеру карты.
Сгенерирован список оставшихся элементов данных
Процесс занял около 75 секунд.
Затем я попытался повторить шаги 1) и 2), используя принятый ответ - примерно через 10 минут это около 7% пути удаления элементов данных. Поэтому я думаю, что приведенное ниже решение примерно на 2 порядка быстрее для этого типа операций.
Вероятно, существуют лучшие реализации двусвязных списков, но я не слишком хорошо знаком ни с одним из них.
namespace Question
{
public class EmployeeCollection
{
private readonly Dictionary<int, ListNode<EmployeeDetails>> _idDictionary = new();
private readonly Dictionary<string, Dictionary<int, EmployeeDetails>> _cardNumberDictionary = new();
private readonly LinkedList<EmployeeDetails> _list = new();
public void AddEmployee(EmployeeDetails details)
{
var node = new ListNode<EmployeeDetails>(details);
_list.AddToStart(node);
_idDictionary.Add(details.Id, node);
if (!_cardNumberDictionary.ContainsKey(details.CardNumber))
{
_cardNumberDictionary.Add(details.CardNumber, new Dictionary<int, EmployeeDetails>());
}
_cardNumberDictionary[details.CardNumber].Add(details.Id, details);
}
public void RemoveById(int id)
{
if (_idDictionary.TryGetValue(id, out var node))
{
_idDictionary.Remove(id);
_list.Remove(node);
var list = _cardNumberDictionary[node.Value.CardNumber];
list.Remove(id);
if (list.Count == 0)
{
_cardNumberDictionary.Remove(node.Value.CardNumber);
}
}
}
public void RemoveByCardNumber(string cardNumber)
{
if (_cardNumberDictionary.TryGetValue(cardNumber, out var employees))
{
_cardNumberDictionary.Remove(cardNumber);
foreach (var employee in employees)
{
if (_idDictionary.TryGetValue(employee.Key, out var node))
{
_list.Remove(node);
}
}
}
}
public IEnumerable<EmployeeDetails> Employees => _list.GetAllValues();
public EmployeeDetails? GetById(int id)
{
if (_idDictionary.ContainsKey(id))
{
return _idDictionary[id].Value;
}
return null;
}
}
public class EmployeeDetails
{
public int Id { get; init; }
public string Name { get; init; }
public string JobDescription { get; init; }
public string CardNumber { get; init; }
public string Type { get; init; }
public static EmployeeDetails FromData(int id, string details)
{
var parts = details.Split(',');
return new EmployeeDetails
{
Id = id,
Name = parts[0],
JobDescription = parts[1],
CardNumber = parts[2],
Type = parts[3],
};
}
}
public class LinkedList<T>
{
public int Count { get; private set; }
private ListNode<T>? Start { get; set; }
private ListNode<T>? End { get; set; }
public bool IsEmpty => Count == 0;
public void AddToStart(ListNode<T> node)
{
ArgumentNullException.ThrowIfNull(nameof(node));
node.Next = null;
node.Previous = null;
if (IsEmpty)
{
Start = End = node;
}
else
{
Start!.Previous = node;
node.Next = Start;
Start = node;
}
Count++;
}
public void Remove(ListNode<T> node)
{
if (node != Start)
{
node.Previous!.Next = node.Next;
}
else
{
Start = node.Next;
}
if (node != End)
{
node.Next!.Previous = node.Previous;
}
else
{
End = node.Previous;
}
Count--;
}
public IEnumerable<T> GetAllValues()
{
var counter = Start;
while (counter != null)
{
yield return counter.Value;
counter = counter.Next;
}
}
}
public class ListNode<T>
{
public T Value { get; }
public ListNode<T>? Previous { get; set; }
public ListNode<T>? Next { get; set; }
public ListNode(T value)
{
Value = value;
}
}
}
в словаре большое количество записей?