Accessing dictionary value element when there are multiple values - c#

foreach (var file in d.GetFiles("*.csv"))
{
using (var reader = new StreamReader(file.FullName))
{
List<string> columns = new List<string>();
string colLine = File.ReadLines(file.FullName).First(); // gets the first line from file.
columns = colLine.Split(',').ToList();
reader.ReadLine(); // skip first line
dynamic x = new ExpandoObject();
var eoa = (IDictionary<string, object>)x;
while (!reader.EndOfStream)
{
var line = reader.ReadLine();
var values = line.Split(',');
for (int idx = 0; idx < values.Length; idx++)
{
if (values[idx] == "\"\"")
{
values[idx] = "[BLANK]";
}
}
int i = 0;
foreach (var value in values)
{
List<string> val = new List<string>();
val.Add(value);
if (!eoa.ContainsKey(columns.ElementAt(i)))
{
eoa.Add(columns.ElementAt(i), val);
}
else
{
List<string> overwrite = new List<string>();
var curr = eoa[columns.ElementAt(i)];
foreach (var v in (dynamic)curr)
{
overwrite.Add(v);
}
overwrite.Add(value);
eoa[columns.ElementAt(i)] = overwrite;
}
i++;
}
}
using (StreamWriter outFile = new StreamWriter(path + #"\output.txt"))
{
foreach (var entry in eoa)
{
var test = entry.Value as List;
outFile.Write("{0}:{1} ", entry.Key, entry.Value);
}
}
}
}
I'm currently unable to get the value of an index belonging to the test variable. I try doing test[0] but get the error "Cannot apply indexing with [] to an expression of type 'object'. I am curious what other ways I can attempt so that these list elements can be accessed which belong to the Value of my dictionary.

Your value seems to be of type object, and as the error suggests you can't directly apply indexing to it. You have to cast it to a List<string> to use test[0].

Related

Subscribe to an Mqtt broker and write into OPC server using windows Forms Application

I'm trying to subscribe to an MQTT broker and write into an OPC server using windows forms application. But I have some problems I get always an exception "Object reference not set to an instance of an object." everything is good but when i arrived to write into an opc server avec subscribing and getting the mqtt message i got an exception. Below is the code This a method in the WCF service.
public void StartTransferFromMQTTtoOPC()
{
try
{
// Check if at least one transfer if configured
string jmsg;
while (TransferHelper.SubscribedBlockingCollection.TryTake(out jmsg))
{
// Check if any transfer is configured.
if (ExportedMQTTTransfers == null || ExportedMQTTTransfers.archList == null ||
ExportedMQTTTransfers.archList.Count == 0)
return;
// check which Mqtt Transfer is responsible for that topic
var message = JsonConvert.DeserializeObject<TopicStruct>(jmsg);
var mqqtmessage = message.Message;
var transfer = ExportedMQTTTransfers.archList.Find(x => x.Topic == message.TopicName);
// get Group Information and server information from the topic
//OPCGroup grp = transfer.OPCgrpsPerServer.TryGetValue()
//Load Configuration of specific topic Fields Mapping
Dictionary<string, string> fieldsmapping;
var first = transfer.OPCgrpsPerServer.First();
OPCGroup grp = first.Value[0];
fieldsmapping = grp.FieldsMapping;
StringBuilder payloadTransformer = new StringBuilder("{\"Iterator\": {\"#loop($.ListofValues)\": {");
foreach (KeyValuePair<string, string> entry in fieldsmapping)
{
payloadTransformer.Append($"\"{entry.Value}\":\"#currentvalueatpath($.{entry.Key})\",");
}
payloadTransformer.Length--;
payloadTransformer.Append("}}}");
string resPayload = JUST.JsonTransformer.Transform(payloadTransformer.ToString(), mqqtmessage);
var myItems = JsonConvert.DeserializeObject<ConsumedItem>(resPayload);
if (myItems is null)
{
return;
}
MappedTags = new Dictionary<string, Dictionary<string, string>>();
List<int> lstItemHandles = new List<int>();
//Read From a CSV file and put data in a Dictionary
string csvFile = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "TagMappings.csv");
var rows = File.ReadAllLines(csvFile);
var totalcols = rows[0].Split(',').Length;
Dictionary<string, string> Y = new Dictionary<string, string>();
string columns = "", csvCell = "";
string[] column;
List<string> MQTTList = new List<string>();
List<string> csvList = new List<string>();
// List<string> GroupNameList = new List<string>();
foreach (var words in rows)
{
columns = words;
column = columns.Split(new[] { ',' }, StringSplitOptions.None);
for (int i = 0; i < column.Length; i++)
{
//if (columns.Split(',')[0].Equals("GroupName"))
//{
// csvCell = columns.Split(',')[i];
// Console.WriteLine(csvCell);
// GroupNameList.Add(csvCell);
//}
if (columns.Split(',')[0].Equals("OPCTag"))
{
csvCell = columns.Split(',')[i];
csvList.Add(csvCell);
}
if (columns.Split(',')[0].Equals("MQTTTag"))
{
csvCell = columns.Split(',')[i];
MQTTList.Add(csvCell);
}
}
Y = csvList.Zip(MQTTList, (k, v) => new { Key = k, Value = v }).ToDictionary(x => x.Value, x => x.Key);
MQTTServiceLogger.TraceLog(MessageType.Control, " Reading CSV file Successfully.");
}
//test Nadia
transfer.Name = "Group0";
MappedTags.Add(grp.GroupName, Y);
// check if retrieved item exist in current group
Dictionary<string, string> tagsmapped = new Dictionary<string, string>();
MappedTags.TryGetValue(transfer.Name, out tagsmapped);
List<OPCItemTransfer> ToBeWriteItems = new List<OPCItemTransfer>();
List<int> Handles = new List<int>();
List<object> Values = new List<object>();
List<string> Items = new List<string>();
foreach (var item in myItems.Iterator)
{
string itemname;
if (tagsmapped.ContainsKey(item.ItemID))
{
//override List of items
tagsmapped.TryGetValue(item.ItemID, out itemname);
item.ItemID = itemname;
ToBeWriteItems.Add(item);
//Items.Add(item.ItemValue);
MQTTServiceLogger.TraceLog(MessageType.Control, "Tags Mapping succeeded .");
}
}
if (ToBeWriteItems.Count == 0)
{
return;
}
OPCItemTransfer item1 = new OPCItemTransfer();
for (int i = 0; i < grp.listItems.Count; i++)
{
lstItemHandles.Add(grp.listItems[i].serverItemHandle);
item1 = ToBeWriteItems.Find(x => x.ItemID == grp.listItems[i].ItemID);
Values.Add(item1.ItemValue);
MQTTServiceLogger.TraceLog(MessageType.Control, "Getting items values Successfully.");
}
if (Values.Count > 0)
{
//2.write to OPC
switch (grp.grpWriteMode)
{
#region Synchronous write
case WriteModes.Synchronous:
{
int[] arrErr;
WriteSynch(grp.ServerIndex,
grp.GroupIndex, lstItemHandles.ToArray(),
Values.ToArray(), out arrErr);
break;
}
#endregion
#region Asynchronous write
case WriteModes.Asynchronous:
{
int cancelID;
int[] arrErr;
int transactionID = 0;
WriteAsynch(grp.ServerIndex, grp.GroupIndex, lstItemHandles.ToArray(),
Values.ToArray(), transactionID, out cancelID, out arrErr);
break;
}
#endregion
#region Synchronous write IO2
case WriteModes.SynchronousIO2:
{
int[] arrErr;
WriteSynch2(grp.ServerIndex,
grp.GroupIndex, lstItemHandles.ToArray(),
Values.ToArray(), out arrErr);
break;
}
#endregion
#region Asynchronous write IO3
case WriteModes.AsynchronousIO3:
{
int cancelID;
int[] arrErr;
int transactionID = 0;
WriteAsynch3(grp.ServerIndex, grp.GroupIndex, lstItemHandles.ToArray(),
Values.ToArray(), transactionID, out cancelID, out arrErr);
break;
}
#endregion
}
}
MQTTServiceLogger.TraceLog(MessageType.Error, "Error while trying to write in an OPC Server.");
}
}
catch (Exception Ex0)
{
//throw;
}
}

Strike through a word in a string PowerPoint interop

I have 2 PowerPoints one original and one edited. I each PowerPoint I have a textbox that contains a number of words. The idea is to find any words added or deleted from the original PowerPoint in the edited and put them in a list. I then want to put a strike though these words that have been added or deleted but I can't access any of the properties I need as I have a string and not a TextFrame. Any ideas how I could strike through the words? E.g original "This Text" edited "This New Text" outcome "This New Text".
My code is as fallows
List<int> originalShapesListID = new List<int>();
List<int> editedShapesListID = new List<int>();
List<int> originalListID = new List<int>();
List<int> editedListID = new List<int>();
List<Microsoft.Office.Interop.PowerPoint.Shape> originalList = new List<Microsoft.Office.Interop.PowerPoint.Shape>();
List<Microsoft.Office.Interop.PowerPoint.Shape> editList = new List<Microsoft.Office.Interop.PowerPoint.Shape>();
Microsoft.Office.Interop.PowerPoint.Shape editedShpID;
List<Microsoft.Office.Interop.PowerPoint.Shape> originalListWords = new List<Microsoft.Office.Interop.PowerPoint.Shape>();
List<char> editListWords = new List<char>();
editedShpID = null;
Microsoft.Office.Interop.PowerPoint.Shape originalShpID;
long editedShapeID;
long originalShapeID;
editedShapeID = 0;
originalShapeID = 0;
originalShpID = null;
originalShp = null;
editShp = null;
Microsoft.Office.Interop.PowerPoint.TextFrame txtFrame;
char delimiter = Convert.ToChar(" ");
List<string> one = new List<string>();
List<string> two = new List<string>();
int indexOfWord = 0;
Getting all Text
String pps = "";
foreach (Microsoft.Office.Interop.PowerPoint.Slide slide in Originalslides)
{
foreach (Microsoft.Office.Interop.PowerPoint.Shape originalShape in slide.Shapes)
{
originalShp = originalShape;
if (originalShape.HasTextFrame == Microsoft.Office.Core.MsoTriState.msoTrue)
{
var textFrame = originalShape.TextFrame;
if (textFrame.HasText == Microsoft.Office.Core.MsoTriState.msoTrue)
{
var textRange = textFrame.TextRange;
pps += originalShape.TextFrame.TextRange.Text;
foreach (char word in pps)
{
l.Add(word);
Debug.WriteLine(word);
}
}
}
originalShapesListID.Add(originalShape.Id);
originalShapeID = originalShape.Id;
originalList.Add(originalShape);
}
originalListID.Add(slide.SlideID);
}
foreach (Microsoft.Office.Interop.PowerPoint.Slide slide in EditedSlides)
{
foreach (Microsoft.Office.Interop.PowerPoint.Shape editShape in slide.Shapes)
{
editShp = editShape;
if (editShape.HasTextFrame == Microsoft.Office.Core.MsoTriState.msoTrue)
{
var textFrame = editShape.TextFrame;
if (textFrame.HasText == Microsoft.Office.Core.MsoTriState.msoTrue)
{
var textRange = textFrame.TextRange;
pps += editShape.TextFrame.TextRange.Text;
foreach (char word in pps)
{
l.Add(word);
Debug.WriteLine(word);
}
}
}
editedShapesListID.Add(editShape.Id);
editedShapeID = editShape.Id;
editList.Add(editShape);
}
editedListID.Add(slide.SlideID);
}
Checking if there is an added or deleted word
var q = from original in originalList
join editedTmp in editList on original.Id equals editedTmp.Id into g
from edited in g.DefaultIfEmpty()
select new
{
original,
edited
};
//foreach through both lists
foreach (var item in q)
{
List<string> diff;
var originalString = item.original.TextFrame.TextRange.Text;
var editString = item.edited.TextFrame.TextRange.Text;
var firstStringList = originalString.Split(delimiter).ToList();
var secondStringList = editString.Split(delimiter).ToList();
if (secondStringList.Count() > firstStringList.Count())
{
diff = secondStringList.Except(firstStringList).ToList();
//change to blue for added word
}
else
{
diff = firstStringList.Except(secondStringList).ToList();
// change to red for deleted word
}
}
Updates section
foreach (var word in firstStringList)
{
//check if word matches
if (secondStringList.IndexOf(word, indexOfWord) == -1)
{
// add word to second string in the correct position
secondStringList.Insert(indexOfWord + indexOfWord, word);
}
indexOfWord++;
}
indexOfWord=0;
// Join the secondStringList to make 1 string separated by the space character
item.edited.TextFrame.TextRange.Text = string.Join(" ", secondStringList);

Entity Framework: How to insert data while looping through multiple lists

I am attempting to insert data from two List.
I am able to successfully insert from one List but adding the second list using a foreach loop does not work as expected.
How do I loop through each of these list so that I can insert their values?
Code:
private void InsertList()
{
var listA = new List<string>();
var listB = new List<string>();
//Populate both list by splitting items in listbox
foreach (ListItem item in ListBox1.Items)
{
var components = item.Value.Split('/');
listA.Add(components.First());
listB.Add(components.Last());
}
using (DataContext dataContext = new DataContext())
{
foreach (var itemA in listA)
{
foreach (var itemB in listB)
{
LIST_OBJECTS listObject = new LIST_OBJECTS
{
LIST_ITEM_A = itemA,
LIST_ITEM_B = itemB
};
dataContext.LIST_OBJECTS.Add(listObject);
}
}
dataContext.SaveChanges();
}
}
What about a for loop?
for (var i = 0; i < listA.Count; i++)
{
LIST_OBJECTS listObject = new LIST_OBJECTS
{
LIST_ITEM_A = listA[i],
LIST_ITEM_B = listB[i]
};
dataContext.LIST_OBJECTS.Add(listObject);
}
Since you know from the creation of the Lists that they'll have the same number of elements, this is fine.
You can do it with LINQ
LIST_OBJECTS listObject = listA.Join(listB,
a=>listA.Indexof(a),
b=>listB.Indexof(b),
(a,b)=> new LIST_OBJECTS()
{
LIST_ITEM_A =a,
LIST_ITEM_B =b
}).ToList();

How do I make List of Lists? And then add to each List values?

class ExtractLinks
{
WebClient contents = new WebClient();
string cont;
List<string> links = new List<string>();
List<string> FilteredLinks = new List<string>();
List<string> Respones = new List<string>();
List<List<string>> Threads = new List<List<string>>();
public void Links(string FileName)
{
HtmlDocument doc = new HtmlDocument();
doc.Load(FileName);
foreach (HtmlNode link in doc.DocumentNode.SelectNodes("//a[#href]"))
{
HtmlAttribute att = link.Attributes["href"];
if (att.Value.StartsWith("http://rotter.net/forum/scoops1"))
{
links.Add(att.Value);
}
}
for (int i = 0; i < links.Count; i++)
{
int f = links[i].IndexOf("#");
string test = links[i].Substring(0, f);
FilteredLinks.Add(test);
}
for (int i = 0; i < FilteredLinks.Count; i++)
{
contents.Encoding = System.Text.Encoding.GetEncoding(1255);
cont = contents.DownloadString(FilteredLinks[i]);
GetResponsers(cont);
}
}
private void GetResponsers(string contents)
{
int f = 0;
int startPos = 0;
while (true)
{
string firstTag = "<FONT CLASS='text16b'>";
string lastTag = "&n";
f = contents.IndexOf(firstTag, startPos);
if (f == -1)
{
break;
}
int g = contents.IndexOf(lastTag, f);
startPos = g + lastTag.Length;
string responser = contents.Substring(f + firstTag.Length, g - f - firstTag.Length);
foreach (List<string> subList in Threads)
{
}
}
}
}
I created this variable :
List<List<string>> Threads = new List<List<string>>();
The first thing I don't know yet how to do is how to create inside Threads number of Lists according to the FilteredLinks.Count inside the Links method.
Second thing is in the GetResponsers method I did:
foreach (List<string> subList in Threads)
{
}
But what I want is that first time it will add all the values from variable responser to the first List in Threads. Then when it's getting to the break; it stop then and then in the Links methods its calling GetResponsers(cont); again this time I want that all the values in responser to be added to the second List in Threads.
I know that each time it's getting to the break; it will get the next FilteredLink from FilteredLinks.
How do I create number of Lists in Threads according to the FilteredLinks.Count?
How do I make the code in GetResponsers to add the responser ?
You don't need to specify the count for the number of lists in Threads, since it is a list, you can simply keep adding lists to it. So the first part is correct where you are declaring it.
The second part --> Your calling method will change. Look below for the calling method.
The third part --> Change private void GetResponsers(string contents) to private void GetResponsers(List threadList, string contents). Look below for implementation change.
Also the loop will look like this then
//other code you have
List<List<string>> Threads = new List<List<string>>();
public void Links(string FileName)
{
// ...other code you have
for (int i = 0; i < FilteredLinks.Count; i++)
{
threads.Add(new List<string>);
contents.Encoding = System.Text.Encoding.GetEncoding(1255);
cont = contents.DownloadString(FilteredLinks[i]);
GetResponsers(threads[threads.Count - 1], cont);
}
}
private void GetResponsers(List<string> threadList, string contents)
{
int f = 0;
int startPos = 0;
while (true)
{
string firstTag = "<FONT CLASS='text16b'>";
string lastTag = "&n";
f = contents.IndexOf(firstTag, startPos);
if (f == -1)
{
break;
}
int g = contents.IndexOf(lastTag, f);
startPos = g + lastTag.Length;
string responser = contents.Substring(f + firstTag.Length, g - f - firstTag.Length);
threadList.Add(responser);
}
}
PS: Please excuse the formatting.
How do i make List of Lists ? And then add to each List values?
The following codesnippet demonstrates you, how to handle List<List<string>>.
List<List<string>> threads = new List<List<string>>();
List<string> list1 = new List<string>();
list1.Add("List1_1");
list1.Add("List1_2")
threads.Add(list1);
List<string> list2 = new List<string>();
list1.Add("List2_1");
list1.Add("List2_2")
list1.Add("List2_3")
threads.Add(list2);
How do i create number of Lists in Threads according to the
FilteredLinks.Count ?
for(int i = 0; i < FilteredLinks.Count; i++)
{
var newList = new List<string>();
newList.Add("item1"); //add whatever you wish, here.
newList.Add("item2");
Threads.Add(newList);
}
I'm afraid I can't help you with Question #2, since I don't understand what you try to achieve there exactly.

Linq write new list from old list sublist, change said list, write back to old list

I'm rather new to Linq. I'm having trouble coding this.
I have a list with many different sublists.
oldList[0] some type
oldList[1] another different type
oldList[2] the type I want
oldList[3] more types
I want to select all the parameters from a specific type and write them to a temp list.
If that temp list is empty, I want to assign some values (values don't actually matter).
After changing the values, I want to write temp list back into oldList.
Please advise. This is a huge learning experience for me.
public void myFunction(list)
{
//list contains at least 5 sublists of various type
//check if the type I want is null
IEnumerable<TypeIWant> possiblyEmptyList = list.OfType<TypeIWant>(); //find the type I want from the list and save it
if (possiblyEmptyList == null) //this doesn't work and possiblyEmptyList.Count <= 1 doesn't work
{
//convert residence address to forwarding address
IEnumerable<ReplacementType> replacementList = list.OfType<ReplacementType>();
forwardingAddress = replacementList.Select(x => new TypeIWant /* this statement functions exactly the way I want it to */
{
Address1 = x.Address1,
Address2 = x.Address2,
AddressType = x.AddressType,
City = x.City,
CountryId = x.CountryId,
CountyRegion = x.CountyRegion,
Email = x.Email,
ConfirmEmail = x.ConfirmEmail,
Fax = x.Fax,
Telephone = x.Telephone,
State = x.State,
PostalCode = x.PostalCode
});
//write forwarding address back to list
//don't know how to do this
}
LINQ purpose is querying. It doesn't allow you to replace some items in collection with other items. Use simple loop instead:
IEnumerable<TypeIWant> possiblyEmptyList = list.OfType<TypeIWant>();
if (!possiblyEmptyList.Any())
{
for (int i = 0; i < list.Count; i++)
{
ReplacementType item = list[i] as ReplacementType;
if (item == null)
continue;
list[i] = ConvertToTypeIWant(item);
}
}
And conversion (which is better to do with something like automapper):
private TypeIWant ConvertToTypeIWant(ReplacementType x)
{
return new TypeIWant
{
Address1 = x.Address1,
Address2 = x.Address2,
AddressType = x.AddressType,
City = x.City,
CountryId = x.CountryId,
CountyRegion = x.CountyRegion,
Email = x.Email,
ConfirmEmail = x.ConfirmEmail,
Fax = x.Fax,
Telephone = x.Telephone,
State = x.State,
PostalCode = x.PostalCode
};
}
Not LINQ but an example.
class Program
{
static void Main(string[] args)
{
// Vars
var list = new List<List<string>>();
var a = new List<string>();
var b = new List<string>();
var c = new List<string> { "one", "two", "three" };
var d = new List<string>();
// Add Lists
list.Add(a);
list.Add(b);
list.Add(c);
list.Add(d);
// Loop through list
foreach (var x in list)
{
if (x.Count < 1)
{
var tempList = new List<string>();
tempList.Add("some value");
x.Clear();
x.AddRange(tempList);
}
}
// Print
int count = 0;
foreach (var l in list)
{
count++;
Console.Write("(List " + count + ") ");
foreach (var s in l)
{
Console.Write(s + " ");
}
Console.WriteLine("");
}
}
}
(List 1) some value
(List 2) some value
(List 3) one two three
(List 4) some value

Categories