SynonymInfo[] For Microsoft.Office.Interop.Word in C# - c#

In C# i using
using word = Microsoft.Office.Interop.Word;
For get a Synonym for words by using this code
var app = new word.Application();
var infosyn = app.SynonymInfo[Wtext[Op + 1].ToString(), word.WdLanguageID.wdArabic];
foreach (var item in infosyn.MeaningList as Array)
{
listBox1.Items.Add(item.ToString());
}
Image here
My Issue is i got only the meaning list ( What is red boxes in image), but i want all words like in the image ( words in red boxes and blue arrows, The whole list).
Note: i use Meaninglist, RelatedWordList and it's not working and make loops in loop take a each synonym words and check their synonyms. Like This
var apps = new words.Application();
var infosyns = apps.SynonymInfo[item.ToString(), words.WdLanguageID.wdArabic] ;
foreach (var iitem in infosyns.MeaningList as Array)
{
listBox1.Items.Add(iitem.ToString());
var appss = new wordss.Application();
var infosynss = appss.SynonymInfo[iitem.ToString(),wordss.WdLanguageID.wdArabic] ;
foreach (var iiitem in infosyns.MeaningList as Array)
{
listBox1.Items.Add(iiitem.ToString());
}
}
Image here

Oli4 is correct.
You need to loop through the underlying data by doing something like this:
foreach (var iiitem in infosyns.MeaningList as Array)
{
listBox1.Items.Add(iiitem.ToString());
foreach (var item in iiitem.MeaningList)
{
listBox1.Items.Add(item.ToString());
}
}

I had a similar problem, however by looping a predefined amount of times through the results, I got a lot more. This was just a quick code and I believe the efficiency could be improved, However I believe it will get you on the right track. (It is somewhat similar to what you have done.
private static string[] getAllMeanings(Application wordApp, string word, int maxSize = 12,bool addOriginal = false)
{
List<string> stringArr = new List<string>();
if (addOriginal)stringArr.Add(word);
SynonymInfo theSynonyms = wordApp.SynonymInfo[word];
foreach (var Meaning in theSynonyms.MeaningList as Array)
{
if (stringArr.Contains(Meaning) == false) stringArr.Add((string)Meaning);
}
for (int ii = 0; ii < stringArr.Count; ii++)
{
theSynonyms = wordApp.SynonymInfo[stringArr[ii]];
foreach (string Meaning in theSynonyms.MeaningList as Array)
{
if (stringArr.Contains(Meaning)) continue;
stringArr.Add(Meaning);
}
if (stringArr.Count >= maxSize) return stringArr.ToArray();
}
return stringArr.ToArray();
}
Basically this function gets all the related words and then recursively adds the related word and finds their related words. This ends up by very closely resembling your result if you set the maxSize to 15;
Note: maxSize is to stop the function, for instance the word "have" has at least 3600 'synonyms'. And optimally your result should remain relevant.

Related

Trying to read the previous line when reading a certain line from a text file in C#

I'm reading a text file that contains continents , countries , capitals and the population of those countries. Here is the text file image of file with info. I then input a value , let's say I input "Birmanie" the StreamReader instance then takes the info from the NEXT line which would be "Bolivie". "Pays" is the input. My goal is to read the line of the country that the user inputs and then later on extract the info from that line.
Here's my code.
while (!srRecherche.EndOfStream)
{
lireLigneRechercher = srRecherche.ReadLine();
if (lireLigneRechercher.IndexOf(Pays,StringComparison.CurrentCultureIgnoreCase) >= 0)
{
for (int i = 1; i <= 35; i++)
{
lireCharacteres += (char)srRecherche.Read();
}
for (int i = 1; i <= 74; i++)
{
srRecherche.Read();
}
}
}
The for loops are there so that I can skip through the rest of the information and only read the country's name.
Here is an example that might help. The numbers (index positions on the lines) are completely made up, but hopefully you'll see where I'm going. Instead of trying to read with a reader, I would read all the lines and put them into a collection of some sort. I used a struct and a HashSet below, but you could use a class and a List, or a SortedSet, or a Collection, or many other options. By transforming each line into a struct/class, you gain the liberty of doing any sort of analysis or manipulation you want without having to back-track. Since your data seems relatively fixed, you can also gain some advantage by storing the entire list in memory and then finding (in your cached list) what the user asks for with a Where() or FirstOrDefault() instead of reading the file with each new input.
class Program
{
static void Main(string[] args)
{
string userInput = "Birmanie";
var lines = File.ReadAllLines("c:\\myfile.txt");
HashSet<FileLine> fileLines = new();
foreach (var line in lines)
{
var fileLine = new FileLine()
{
Country = line.Substring(0, 25).Trim(),
City = line.Substring(35, 20).Trim(),
Population = Convert.ToInt32(line.Substring(55, 20).Trim()),
Continent = line.Substring(75).Trim()
};
fileLines.Add(fileLine);
}
int pop = fileLines.FirstOrDefault(l => l.City == userInput).Population;
}
}
struct FileLine
{
public string Country;
public string City;
public int Population;
public string Continent;
}

Foreach each element, but they may repeat

I have an array of tags that may appear in console as color tags. There's 37 of them.
So, I do this code:
tagsCT is a string[]
foreach (string tag in tagsCT)
{
if (text.Contains(tag))
{
ArrayList x = new ArrayList();
x.Add(tag);
x.Add(tagsColorValues[k]);
tagss.Add(text.IndexOf(tag));
tags.Add(text.IndexOf(tag) - 1, x);
}
k++;
}
What do I have:
text = "2013-11-11 17:56:14 [INFO] $4/time: $5Changes the time on each world"
What I need to do is find all the color tags in the string. All the possible ones are
in an array string[]
tagsCT = { "$1","$2","$3","$4" }
I show it as an example, but the tags aren't always the same length.
But the problem strikes in these situations:
text = "2013-11-11 17:56:14 [INFO] $4/time: $5Changes the time on each $4world"
The last tag will not be detected. The question is how to prevent it.
You could use a Dictionary<string, IList<int>> instead:
var tagIndices = new Dictionary<string, IList<int>>();
foreach (string tag in tagsCT)
{
IList<int> indices;
if (tagIndices.TryGetValue(tag, out indices))
continue; // to prevent the same indices on duplicate tags, you could also use a HashSet<string> instead of the array
else
{
indices = new List<int>();
tagIndices.Add(tag, indices);
}
int index = text.IndexOf(tag);
while (index >= 0)
{
indices.Add(index);
index = text.IndexOf(tag, index + 1);
}
}
Each tag is stored as key and the value is the list of indices (can be empty).
Here's a demonstration
How about, after you've processed the tag, remove it from the "text" string?
You could also use a for(int i;;i) structure using the IndexOf value.
(sorry, where the hell is he comment button then?)

Using C#, how do I read a text file into a matrix of characters and then query that matrix? Is this even possible?

Example
If I had a text file with these lines:
The cat meowed.
The dog barked.
The cat ran up a tree.
I would want to end up with a matrix of rows and columns like this:
0 1 2 3 4 5 6 7 8 9
0| t-h-e- -c-a-t- -m-e-o-w-e-d-.- - - - - - - -
1| t-h-e- -d-o-g- -b-a-r-k-e-d-.- - - - - - - -
2| t-h-e- -c-a-t- -r-a-n- -u-p- -a- -t-r-e-e-.-
Then I would like to query this matrix to quickly determine information about the text file itself. For example, I would quickly be able to tell if everything in column "0" is a "t" (it is).
I realize that this might seem like a strange thing to do. I am trying to ultimately (among other things) determine if various text files are fixed-width delimited without any prior knowledge about the file. I also want to use this matrix to detect patterns.
The actual files that will go through this are quite large.
Thanks!
For example, I would quickly be able to tell if everything in column "0" is a "t" (it is).
int column = 0;
char charToCheck = 't';
bool b = File.ReadLines(filename)
.All(s => (s.Length > column ? s[column] : '\0') == charToCheck);
What you can do is read the first line of your text file and use it as a mask. Compare every next line to the mask and remove every character from the mask that is not the same as the character at the same position. After processing al lines you'll have a list of delimiters.
Btw, code is not very clean but it is a good starter I think.
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
namespace DynamicallyDetectFixedWithDelimiter
{
class Program
{
static void Main(string[] args)
{
var sr = new StreamReader(#"C:\Temp\test.txt");
// Get initial list of delimiters
char[] firstLine = sr.ReadLine().ToCharArray();
Dictionary<int, char> delimiters = new Dictionary<int, char>();
for (int i = 0; i < firstLine.Count(); i++)
{
delimiters.Add(i, firstLine[i]);
}
// Read subsequent lines, remove delimeters from
// the dictionary that are not present in subsequent lines
string line;
while ((line = sr.ReadLine()) != null && delimiters.Count() != 0)
{
var subsequentLine = line.ToCharArray();
var invalidDelimiters = new List<int>();
// Compare all chars in first and subsequent line
foreach (var delimiter in delimiters)
{
if (delimiter.Key >= subsequentLine.Count())
{
invalidDelimiters.Add(delimiter.Key);
continue;
}
// Remove delimiter when it differs from the
// character at the same position in a subsequent line
if (subsequentLine[delimiter.Key] != delimiter.Value)
{
invalidDelimiters.Add(delimiter.Key);
}
}
foreach (var invalidDelimiter in invalidDelimiters)
{
delimiters.Remove(invalidDelimiter);
}
}
foreach (var delimiter in delimiters)
{
Console.WriteLine(String.Format("Delimiter at {0} = {1}", delimiter.Key, delimiter.Value));
}
sr.Close();
}
}
}
"I am trying to ultimately (among other things) determine if various text files are fixed-width (...)"
If that's so, you could try this:
public bool isFixedWidth (string fileName)
{
string[] lines = File.ReadAllLines(fileName);
int length = lines[0].Length;
foreach (string s in lines)
{
if (s.length != Length)
{
return false;
}
}
return true;
}
Once you get that lines variable, you can access any character as though they were in a matrix. Like char c = lines[3][1];. However, there is no hard guarantee that all lines are the same length. You could pad them to be the same length as the longest one, if you so wanted.
Also,
"how would I query to get a list of all columns that contain a space character for ALL rows (for example)"
You could try this:
public bool CheckIfAllCharactersInAColumnAreTheSame (string[] lines, int colIndex)
{
char c = lines[0][colIndex];
try
{
foreach (string s in lines)
{
if (s[colIndex] != c)
{
return false;
}
}
return true;
}
catch (IndexOutOfRangeException ex)
{
return false;
}
}
Since it's not clear where you're have difficulty exactly, here are a few pointers.
Reading the file as strings, one per line:
string[] lines = File.ReadAllLines("filename.txt");
Obtaning a jagged array (a matrix) of characters from the lines (this step seems unnecessary since strings can be indexed just like character arrays):
char[][] charMatrix = lines.Select(l => l.ToCharArray()).ToArray();
Example query: whether every character in column 0 is a 't':
bool allTs = charMatrix.All(row => row[0] == 't');

C# Exclude Array Object

I have a slight problem with this code:
string[] sWords = {"Word 1", "Word2"}
foreach (string sWord in sWords)
{
Console.WriteLine(sWord);
}
This works fine if I want every object to print.
I was wondering if I could exclude the first item in the array?
So it would only output "Word 2". I know the obvious solution is not to include the first item but in this case I can't.
Using LINQ to Objects, you can just use Skip:
foreach (string word in words.Skip(1))
{
Console.WriteLine(word);
}
Using LINQ in .Net 3.5 and up:
string[] words = {"Word 1", "Word2"}
foreach (string word in words.Skip(1))
{
Console.WriteLine(word);
}
Note that you must have a using System.Linq; statement at the top of your file, as Skip is an extension method.
An alternative option is to use a regular for loop:
for( int x = 1; x < words.Length; ++x )
Console.WriteLine(words[x]);
I also strongly discourage the use of Hungarian-like prefixes in variable names in .Net.
You can use a for loop instead:
string[] sWords = {"Word 1", "Word2"};
var len = sWords.Length;
for (int i = 1; i < len; i++)
{
Console.WriteLine(sWords[i]);
}
You could do
string[] sWords = {"Word 1", "Word2"};
for(int i=1; i<sWords.Length; i++)
{
Console.WriteLine(sWord[i]);
}

Sort search results from text file into listbox

what i have is a textbox into which the user types a string. The string will look something like this:
G32:04:20:40
Then the user hits the search button. The program must then open a textfile and search for the "nearest" five strings to the one they entered and display them in a listbox.
I'll define "nearest string" as much as i can (most likely using a very long complicated example).
The data contained in the text file looks like this:
G32:63:58:11 JG01
G32:86:98:30 JG01
G33:50:05:11 JG06
G33:03:84:12 JG05
G34:45:58:11 JG07
G35:45:20:41 JG01
G35:58:20:21 JG03
So if the user types in the string :
G33:89:03:20
The five closest results should display in the list box like this:
G33:50:05:11 JG06
G33:03:84:12 JG05
G32:86:98:30 JG01
G32:63:58:11 JG01
G34:45:58:11 JG07
I should probably point out at this point that strings are coordinates and the value after "JG" represents the value of something at that coordinate.
The way i got to those 5 is by going through the string piece by piece. So the user typed in "G33" so i find all those with G33 at the beginning - if there are none then i find the closest to G33. Then it was "89" so i find all those where the next part is "89" if there are none, then the closest to 89 the better and so on.
What i need to know is how do i go about doing this? I've built the visual components and i also have code in place that deals with similar kinds of things but when it comes to this i'm truely stumped. As you can probably tell by now, i'm rather new to C#, but i'm learning :)
EDIT: Search Code
private void btnSearch_Click(object sender, EventArgs e)
{
lstResult.Items.Clear();
if (txtSearch.Text == String.Empty)
{
MessageBox.Show("The textbox is empty, there is nothing to search.",
"Textbox empty", MessageBoxButtons.OK, MessageBoxIcon.Information);
}
else
{
this.CheckFormatting();
}
}
private long GetIndexForCoord(string coord)
{
// gets out a numerical value for each coordinate to make it easier to compare
Regex m_regex = new Regex("\\d\\d:\\d\\d:\\d\\d:\\d\\d");
string cleaned = m_regex.Match(coord).Value;
cleaned = cleaned.Replace(':', '0');
return Convert.ToInt64(cleaned);
}
private List<string> GetResults(string coord)
{
// gets out the 5 closest coordinates
long index = GetIndexForCoord(coord);
// First find the 5 closest indexes to the one we're looking for
List<long> found = new List<long>();
while (found.Count < 5)
{
long closest = long.MaxValue;
long closestAbs = long.MaxValue;
foreach (long i in m_indexes)
{
if (!found.Contains(i))
{
long absIndex = Math.Abs(index - i);
if (absIndex < closestAbs)
{
closest = i;
closestAbs = absIndex;
}
}
}
if (closest != long.MaxValue)
{
found.Add(closest);
}
}
// Then use those indexes to get the coordinates from the dictionary
List<string> s = new List<string>();
foreach (long i in found)
{
s.Add(m_dic[i]);
}
return s;
}
private void CheckFormatting()
{
StringReader objReader = new StringReader(txtSearch.Text);
bool FlagCheck = true;
if (!Regex.IsMatch(txtSearch.Text,
"G3[0-9]{1}:[0-9]{2}:[0-9]{2}:[0-9]{2}"))
{
FlagCheck = false;
}
if (FlagCheck == true)
{
this.CheckAndPopulate();
}
else
{
MessageBox.Show("Your search coordinates are not formatted correctly.",
"Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
}
}
private void CheckAndPopulate()
{
StreamReader objReader = new StreamReader("Jumpgate List.JG");
List<String> v = new List<String>();
do
{
v.Add(objReader.ReadLine());
}
while (objReader.Peek() != -1);
objReader.Close();
foreach (string c in v)
{
long index = GetIndexForCoord(c);
m_dic.Add(index, c);
m_indexes.Add(index);
}
List<string> results = GetResults(txtSearch.Text);
foreach (string c in results)
{
lstResult.Items.Add(c);
}
}
Edit: Added suggested code to read in the file. And also an explanation at the end.
Edit2: Added if check around the adding to the dictionary/list to handle duplicates.
Please note, this code is almost certainly quite inefficient (except possibly by accident) and would need to be cleaned up and error handling would need to be added etc, but it might give you a starting point for writing better code at least.
You probably want to take a look at k-nearest neighbor algorithm to find out the proper way of doing this.
I've assumed that the letter in the beginning is always G and that all 4 parts of the coordinates are always 2 digits each.
Add the following 2 to your class/form:
Dictionary<long, string> m_dic = new Dictionary<long, string>();
List<long> m_indexes = new List<long>();
Then initialize them with the following code (I've assumed you've already read in all the coordinates into a string array called v with one coordinate per item):
foreach (string c in v)
{
long index = GetIndexForCoord(c);
if(!m_dic.ContainsKey(index))
{
m_dic.Add(index, c);
m_indexes.Add(index);
}
}
Then add the following 2 methods:
// gets out a numerical value for each coordinate to make it easier to compare
private long GetIndexForCoord(string coord)
{
Regex m_regex = new Regex("\\d\\d:\\d\\d:\\d\\d:\\d\\d");
string cleaned = m_regex.Match(coord).Value;
cleaned = cleaned.Replace(':', '0');
return Convert.ToInt64(cleaned);
}
// gets out the 5 closest coordinates
private List<string> GetResults(string coord)
{
long index = GetIndexForCoord(coord);
// First find the 5 closest indexes to the one we're looking for
List<long> found = new List<long>();
while (found.Count < 5)
{
long closest = long.MaxValue;
long closestAbs = long.MaxValue;
foreach (long i in m_indexes)
{
if (!found.Contains(i))
{
long absIndex = Math.Abs(index - i);
if (absIndex < closestAbs)
{
closest = i;
closestAbs = absIndex;
}
}
}
if (closest != long.MaxValue)
{
found.Add(closest);
}
}
// Then use those indexes to get the coordinates from the dictionary
List<string> s = new List<string>();
foreach (long i in found)
{
s.Add(m_dic[i]);
}
return s;
}
And finally when the user enter the data you send in that data to the method as:
List<string> results = GetResults(lookingFor);
You can then use the results to populate your listbox.
The code works by converting each coordinate to a numerical value called index (since it's easier to work with) and it then adds all the coordinates to a dictionary with the index as the key.
When it's looking up the closest coordinates it compares the difference in value between the index you're looking for and each of the previously stored indexes to find the 5 closest ones (it uses the Math.Abs method so that it can get the difference without having to worry about negative numbers). It's quite inefficient since it loops through each value once for each coordinate you want to find (so if your list contains 1000 coordinates and you want to find the 5 closest, it'll go through the inner loop 5000 times, I'd assume that could probably be cut down to just 1000 times by improving the code, I suggest looking at the wiki link close to the top of this answer for a better algorithm).

Categories